Gunakan penguncian tingkat baris secara eksplisit di subkueri terurut di semua kueri yang bersaing .
(SELECT
tidak bersaing dengan kunci tulis.)
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;
Dengan cara ini, baris dikunci dalam urutan yang konsisten seperti yang disarankan dalam manual.
Dengan asumsi bahwa id_A
, id_B
tidak pernah diperbarui, bahkan komplikasi kasus sudut yang jarang seperti yang dirinci dalam kotak "Perhatian" di manual tidak dimungkinkan.
Meskipun tidak memperbarui kolom kunci, Anda dapat menggunakan mode kunci yang lebih lemah FOR NO KEY UPDATE
. Memerlukan Postgres 9.3 atau lebih baru.
Yang lain (lambat dan yakin) adalah menggunakan Level Isolasi Serializable untuk transaksi yang bersaing. Anda harus bersiap untuk kegagalan serialisasi, dalam hal ini Anda harus mencoba kembali perintah tersebut.