PostgreSQL 中有一种锁定机制,称为advisory locking。 .它提供以下 API functions .
允许我们获得这种锁的函数接受一个大整数参数:pg_advisory_lock(key bigint)
或两个整数键:pg_advisory_lock(key1 int, key2 int)
(第二种形式)。
我可以使用什么抽象机制来使用字符串键而不是整数键?也许一些散列函数能够完成这项工作?
是否可以仅在 PostgreSQL 中实现这一点,而无需在应用程序级别将字符串转换为整数?
如果难以实现预期的目标,也许我可以使用两个整数来标识表中的行。第二个整数可以是行的主键,但我可以使用什么整数作为表标识符?
最佳答案
您已经找到了最有可能的候选者:使用表的合成主键加上表标识符作为键。
您可以使用来自 pg_class
的表的 oid(对象标识符)来指定表。转换为伪类型 regclass
的便利为您查找,或者您可以 select c.oid from pg_class c inner join pg_namespace n where n.nspname = 'public' and c. relname = 'mytable'
按模式获取它。
有一个小问题,因为 oid
在内部是一个无符号的 32 位整数,但是 pg_advisory_lock
的双参数形式需要一个有符号 整数。这在实践中不太可能成为问题,因为在这成为问题之前您需要检查很多 OID。
例如
SELECT pg_advisory_lock('mytable'::regclass::integer, 42);
但是,如果您要这样做,您基本上是在使用咨询锁来模拟行锁定。那么为什么不直接使用行锁定呢?
SELECT 1
FROM mytable
WHERE id = 42
FOR UPDATE OF mytable;
现在,如果您真的必须使用字符串键,您将不得不接受会发生冲突,因为您将使用相当小的散列。
PostgreSQL 具有用于哈希连接的内置哈希函数。它们不是加密散列——它们被设计为速度很快并且产生的结果相当小。这就是您为此目的所需要的。
它们实际上散列为 int4,而您真的更喜欢 int8,因此您会面临更高的冲突风险。不过,另一种方法是采用像 md5 这样的慢速加密散列并截断它,但这很丑陋。
所以如果你真的、真的觉得你必须这么做,你可以这样做:
select pg_advisory_lock( hashtext('fredfred') );
...但前提是您的应用能够处理其他字符串不可避免地会产生相同散列的事实,因此您可能会看到未真正锁定的行被“锁定”。
关于postgresql - 如何使用字符串作为 PostgreSQL 咨询锁的键?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29353845/