Ответ 1
Вы уже попали на наиболее вероятного кандидата: используя синтетический первичный ключ таблицы плюс идентификатор таблицы в качестве ключа.
Вы можете использовать таблицу oid (идентификатор объекта) из pg_class
, чтобы указать таблицу. Удобство, наложенное на псевдо-тип 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') );
... но только если ваше приложение может справиться с тем фактом, что неизбежно, что другие строки могут создавать один и тот же хэш, поэтому вы можете увидеть строку как "заблокированную", которая по-настоящему не заблокирована.