PostgreSQL
 sql >> Datenbank >  >> RDS >> PostgreSQL

Konsistenz in postgresql mit Sperren und Auswahl für Aktualisierung

BEGIN; 
LOCK TABLE slots IN ACCESS EXCLUSIVE MODE; 
UPDATE slots SET job_name = '111' WHERE id IN (SELECT id FROM slots WHERE job_name IS NULL LIMIT 1) RETURNING *;
COMMIT;

Dies scheint in Read Committed zu funktionieren. Es ist nur SQL (dasselbe wie Ihr Code) und kann in einem Aufruf ausgeführt werden (schneller).

@Seth Robertson:Ohne LOCK TABLE und ohne While-Schleife ist es nicht sicher.

Wenn Transaktion A und Transaktion B gleichzeitig vorhanden sind:A wählt die erste Zeile aus und B wählt die erste Zeile aus. A sperrt und aktualisiert die Zeile, B muss warten, bis A festschreibt. Dann überprüft B erneut die Bedingung job_name IS NULL. Es ist falsch und B wird nicht aktualisiert - B wählt nicht die nächste Zeile aus, sondern prüft nur erneut und gibt ein leeres Ergebnis zurück.

@joegester:SELECT FOR UPDATE ist nicht das Problem, da alle Tabellen gesperrt sind.

Vielleicht gibt es eine andere Möglichkeit, die Arbeit zu erledigen - wenn Sie Zeilen löschen und einfügen (in einer anderen Tabelle?), Setzen Sie stattdessen NULL. Aber ich bin mir nicht sicher wie.