Usar bloqueo explícito a nivel de fila en subconsultas ordenadas en todas las consultas de la competencia .
(SELECT
no compite con los bloqueos de escritura).
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;
De esta manera, las filas se bloquean en el mismo orden que se recomienda en el manual.
Suponiendo que id_A
, id_B
nunca se actualizan, incluso las complicaciones raras de casos de esquina como se detalla en el cuadro "Precaución" en el manual no son posibles.
Mientras no actualice las columnas clave, puede usar el modo de bloqueo más débil FOR NO KEY UPDATE
. Requiere Postgres 9.3 o posterior.
El otro (lento y seguro) es usar el nivel de aislamiento serializable para transacciones competidoras. Debería prepararse para las fallas de serialización, en cuyo caso debe volver a intentar el comando.