Sperrenden Benutzer herausfinden

Hi Leutz.
Ich hoffe ich poste mein Problem im richtigen Thread.
Es geht um folgendes. Ich Sperre in meinem Java-Programm einen bestimmten Datensatz mittels einem SQL Befehl

SELECT * FROM hallo WHERE id = '90' FOR UPDATE NOWAIT

Das funktioniert alles soweit.
Jetzt will ich mir den User der genau diesen Satz sperrt holen.
Ich bin schon soweit das ich sehe wer alles in dieser Tabelle Sätze sperrt aber weiss einfach nicht weiter.
Mir fehlt eigentlich nur der Key des gesperrten Satzes…
hier mal meine SQL-Abfrage(soweit ich bin)

/* ALLE Tabellen die mit einem RowExclusiveLock belegt sind */
SELECT pg_stat_activity.query_start,
    pg_locks.pid,
    coalesce(pg_class.relname,'TMP-OBJECT') as relname,
    pg_stat_activity.usename
FROM
    pg_stat_activity
    ,pg_locks LEFT OUTER JOIN pg_class
    ON pg_locks.relation = pg_class.oid
WHERE pg_locks.pid=pg_stat_activity.procpid
and pg_locks.locktype != 'transactionid'
and pg_locks.mode like 'RowExclusiveLock'
and relname = 'hallo'
/*jetzt fehlt nur noch etwas das so in der art aussehen müsste*/
/*and KeyDesGesperrtenSatzes = 90 */
;

plz Help

gruss
MScalli

Darf ich zuerst fragen, was du mit dieser Information bezweckst?

Was du da versuchst, greift auf die Systemtabellen zu. Diese ändern sich jedoch von Version zu Version, daher ist dein Programm hochgradig von deiner verwendeten PostgreSQL-Version abhängig.

Ich will eigentlich “nur” raus finden wer den Satz den ich bearbeiten möchte gerade “exclusiv” geöffnet hat.
z.b.
Ein user öffnet einen Kundensatz um diesen zu ändern.
Dies geschieht mit FOR UPDATE NOWAIT.
Der nächste User will genau an diesem Kunden änderungen vornehmen, kann den Satz aber nicht öffnen da er ja exklusiv geöffnte ist.
Nun will ich diesem Kunden aber sagen, pass auf dieser Satz ist gerade im zugriff… und zwar von User XY!

ps: der select oben hat gestern den ganzen tag funktioniert… Jetzt ist ein gesperrter Satz auf einmal im ‘RowShareLock’ und nicht mehr im ‘RowExclusiveLock’…
ich versteh jetzt gar nichts mehr ?!!??!

also das mit dem RowShareLock und RowExclusivLock kann ich jetzt erklären.

öffne ich eine transaktion in meinem Programm mit ‘SELECT … FOR UPDATE’
wird ‘RowShareLock’ gesetzt

wird hingegen z.B. ein ‘UPDATE hallo WHERE id = 90’ ausgeführt
wird ‘RowExclusivLock’ gesetzt

leider weiss ich immer noch nicht wie ich an den sperrenden user komme :frowning:

Nun, FOR UPDATE ist ja erst mal nur ein Lock, um die Möglichkeit zum Bearbeiten sicherzustellen. Nachdem der Datensatz effektiv aktualisiert wurde, muss der gegen weitere Änderungen von anderen gesperrt werden. Dafür wird dann ein “schärferer” Loglevel verwendet.

Ok soweit so gut…
Aber jetzt habe ich imme rnoch das Problem das ich den richtigen Satz nicht kenne.
Ich habe jetzt zwar die Relation aber immer noch nicht den Schlüssel des Satzes… oder wie ich an den gesperrten Satz komme…
kann mir da jetzt wer weiter helfen??

weil ich das thema recht interessant finde, stelle ich hier mal meine pragmatischen experimentierergebnisse zur diskussion:

select d.id, p.usename, l.* 
from my_schema.my_table d
inner join pg_locks l on l.transactionid in in (d.xmin, d.xmax)
inner join pg_stat_activity p on p.procpid = l.pid

der ansatz basiert auf der annahme, dass in pg_locks ja eh nur “aktive” transactions aufgefuehrt sind … daher kann ich da ruhig einfach die xmin und xmax information aus den tupels ranjoinen und erhalten darueber nur zeilen, die gerade in irgendeine dieser transaktionen involviert sind …

d.h. ueber die transaktion dem der lock gehoert weiss ich, dass der satz gerade dieser transaktion “gehoert” …

ein join auf xmax reicht wahrscheinlich aus - da eine modifikation einer zeile ja immer (nach dem commit) zu einer zu loeschenden zeilenversion fuehrt.

das erwaehne ich, weil ein join nur auf xmax viel schneller ausgefuehrt wurde - bei meinen experimenten
also:

...
inner join pg_locks l on l.transactionid in = d.xmax
...

ist schneller.

du solltest beachten das xmin und xmax ALLEIN kein indikator auf einen aktiven lock ist - dazu musst schon noch die pg_locks joinen - weil xmax auch nach einem collback so stehen bleibt

xmin> The identity (transaction ID) of the inserting transaction for this row version. (A row version is an individual state of a row; each update of a row creates a new row version for the same logical row.)



xmax> The identity (transaction ID) of the deleting transaction, or zero for an undeleted row version. It is possible for this column to be nonzero in a visible row version. That usually indicates that the deleting transaction hasn’t committed yet, or that an attempted deletion was rolled back.

das ist zwar naturgemaess sehr postgres-spezifisch … aber ich denke xmax und xmin gibte s schon so lange dass es uns auch noch sehr lang erhalten sein wird … die system views sind ja auch nicht neu