順序付けられたサブクエリで明示的な行レベルのロックを使用する 競合するすべてのクエリで 。
(SELECT
書き込みロックと競合しません。)
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;
このようにして、マニュアルでアドバイスされているように、行は一貫した順序でロックされます。
id_A
と仮定します 、id_B
更新されることはなく、マニュアルの「注意」ボックスに詳述されているようなまれなコーナーケースの複雑化もあり得ません。
キー列を更新していない間は、弱いロックモードを使用できますFOR NO KEY UPDATE
。 Postgres9.3以降が必要です。
もう1つ(遅い そして確かに)オプションは、競合するトランザクションにシリアル化可能な分離レベルを使用することです。シリアル化の失敗に備える必要があります。その場合、コマンドを再試行する必要があります。