No hay ORDER BY
en un SQL UPDATE
comando. 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 UPDATE
en una subconsulta o SELECT
en 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 bar
obviamente 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 SELECT
comando se ejecute a READ COMMITTED
nivel de aislamiento de transacción y use ORDER BY
una 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 DEFERRABLE
restricción para evitar violaciones únicas dentro del mismo comando. Respuesta relacionada:
CREATE TABLE
código.