Verwenden Sie explizites Sperren auf Zeilenebene in geordneten Unterabfragen in allen konkurrierenden Suchanfragen .
(SELECT
konkurriert nicht mit Schreibsperren.)
DELETE
DELETE FROM table_name t
USING (
SELECT id_A, id_B
FROM table_name
WHERE id_A = ANY(array_of_id_A)
AND id_B = ANY(array_of_id_B)
ORDER BY id_A, id_B
FOR UPDATE
) del
WHERE t.id_A = del.id_A
AND t.id_B = del.id_B;
UPDATE
UPDATE table_name t
SET val_1 = 'some value'
, val_2 = 'some value'
FROM (
SELECT id_A, id_B
FROM table_name
WHERE id_A = ANY(array_of_id_A)
AND id_B = ANY(array_of_id_B)
ORDER BY id_A, id_B
FOR NO KEY UPDATE -- Postgres 9.3+
-- FOR UPDATE -- for older versions or updates on key columns
) upd
WHERE t.id_A = upd.id_A
AND t.id_B = upd.id_B;
Auf diese Weise werden Zeilen in konsistenter Reihenfolge gesperrt, wie im Handbuch empfohlen.
Angenommen, id_A
, id_B
werden nie aktualisiert, selbst seltene Komplikationen in Ausnahmefällen, wie im Abschnitt "Achtung" im Handbuch beschrieben, sind nicht möglich.
Während Schlüsselspalten nicht aktualisiert werden, können Sie den schwächeren Sperrmodus FOR NO KEY UPDATE
verwenden . Erfordert Postgres 9.3 oder höher.
Die andere (langsam und sicher) Option ist die Verwendung der serialisierbaren Isolationsstufe für konkurrierende Transaktionen. Sie müssten sich auf Serialisierungsfehler vorbereiten, in diesem Fall müssen Sie den Befehl wiederholen.