Použijte explicitní uzamykání na úrovni řádků v uspořádaných poddotazech ve všech konkurenčních dotazech .
(SELECT
nesoutěží se zámky zápisu.)
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;
Tímto způsobem jsou řádky uzamčeny v konzistentním pořadí, jak je doporučeno v příručce.
Za předpokladu, že id_A
, id_B
se nikdy neaktualizují, dokonce ani vzácné komplikace rohového pouzdra, jak je popsáno v rámečku "Pozor" v příručce, nejsou možné.
I když neaktualizujete klíčové sloupce, můžete použít slabší režim uzamčení FOR NO KEY UPDATE
. Vyžaduje Postgres 9.3 nebo novější.
Druhý (pomalý a jistá) možností je použít pro konkurenční transakce Serializable Isolation Level. Budete se muset připravit na selhání serializace, v takovém případě musíte příkaz zopakovat.