Sie haben bereits den wahrscheinlichsten Kandidaten gefunden: Verwenden eines synthetischen Primärschlüssels einer Tabelle und einer Tabellenkennung als Schlüssel.
Sie können die Tabelle oid (Objekt-ID) von pg_class
verwenden, um die Tabelle anzugeben. Die Bequemlichkeit, die zum Pseudotyp regclass
umgewandelt wird, sucht dieses für Sie, oder Sie können select c.oid from pg_class c inner join pg_namespace n where n.nspname = 'public' and c.relname = 'mytable'
, um es by-schema zu erhalten.
Es gibt ein kleines Problem, weil oid
intern ist ein unsigned 32-Bit-Integer, aber die beiden argument Form von pg_advisory_lock
nimmt eine integer unterzeichnet. Dies ist wahrscheinlich kein Problem in der Praxis, da Sie ein Los von OIDs durchlaufen müssen, bevor das ein Problem ist.
z.B.
SELECT pg_advisory_lock('mytable'::regclass::integer, 42);
Wenn Sie jedoch das zu tun, gehen, bist du im Grunde Reihe emuliert mit beratenden Schlössern verriegelt. Warum also nicht einfach die Zeilensperrung verwenden?
SELECT 1
FROM mytable
WHERE id = 42
FOR UPDATE OF mytable;
Nun, wenn Sie wirklich einen String-Schlüssel verwenden musste, wirst du akzeptieren müssen, dass es Kollisionen sein werde, weil Sie eine ziemlich kleine Hash verwenden werden.
PostgreSQL hat eingebaute Hash-Funktionen, die für Hash-Joins verwendet werden. Sie sind keine kryptografischen Hashes - sie sind so entworfen, dass sie schnell sind und ein ziemlich kleines Ergebnis liefern. Das brauchen Sie für diesen Zweck.
Sie Hash tatsächlich zu int4, und Sie würden wirklich int8 bevorzugen, so dass Sie ein noch höheres Risiko von Kollisionen laufen. Die Alternative ist, einen langsamen kryptografischen Hash wie md5 zu nehmen und ihn zu kürzen, und das ist nur hässlich.
Also, wenn Sie wirklich, wirklich das Gefühl, Sie müssen Sie so etwas wie tun könnte:
select pg_advisory_lock(hashtext('fredfred'));
... aber nur, wenn Ihre Anwendung kann mit der Tatsache fertig werden, dass es unvermeidlich ist, dass andere Saiten die produzieren kann der gleiche Hash, sodass Sie eine Zeile als "gesperrt" sehen, die nicht wirklich gesperrt ist.
Dieser Thread hat Details für 'hashtext()' - warum es nicht dokumentiert ist: http: //www.postgresql.org/message-id/flat/AB615962-28B4-4396-9270-AB56B08BCA8C @ justatheory.com # AB615962-28B4-4396-9270-AB56B08BCA8C @ justatheory.com Versionsunabhängige Funktion von Peter Eisentraut: https://github.com/peter/pgvihash –
Danke für eine klare Erklärung! Ich habe bereits von Tisch OID selbst. Sieht so aus, als wäre es eine bestmögliche Lösung für dieses Problem. –
@ErwinBrandstetter Guter Punkt. Es ist am wichtigsten, sie nicht für Dinge wie benutzerdefinierte Indizes zu verwenden, aber ja, es könnte einige BC-Auswirkungen geben. –