No hay ORDER BYen un SQL UPDATEcomando. Postgres actualiza las filas en orden arbitrario:
Para evitar puntos muertos con absoluta certeza, puede ejecutar sus declaraciones en aislamiento de transacciones serializables . Pero eso es más costoso y debe prepararse para repetir comandos en caso de falla de serialización.
Su mejor curso de acción es probablemente bloquear explícitamente SELECT ... ORDER BY ... FOR UPDATEen una subconsulta o SELECTen una transacción independiente, en el nivel de aislamiento predeterminado "lectura confirmada". Citando a Tom Lane en pgsql-general :
Debería estar bien --- el bloqueo FOR UPDATE siempre es el último paso en la tubería SELECT.
Esto debería hacer el trabajo:
BEGIN;
SELECT 1
FROM foo
WHERE baz = 1234
ORDER BY bar
FOR UPDATE;
UPDATE foo
SET bar = bar + 1
WHERE baz = 1234;
COMMIT;
Un índice de varias columnas (baz, bar)puede ser perfecto para el rendimiento. Pero como barobviamente se actualiza mucho , un índice de una sola columna (baz)podría ser aún mejor. Depende de un par de factores. ¿Cuántas filas por baz? ¿Son posibles las actualizaciones HOT sin el índice de varias columnas? ...
Si baz se actualiza al mismo tiempo, todavía hay una posibilidad improbable de conflictos en el caso de la esquina (según la documentación) :
Es posible que un SELECTcomando se ejecute a READ COMMITTED
nivel de aislamiento de transacción y use ORDER BYuna cláusula de bloqueo para devolver las filas fuera de servicio. ...
Además, si debe tener una restricción única que implique bar, considere una DEFERRABLErestricción para evitar violaciones únicas dentro del mismo comando. Respuesta relacionada:
CREATE TABLEcódigo.