Нет ORDER BYв SQL UPDATEкоманде. Postgres обновляет строки в произвольном порядке:
Чтобы избежать взаимных блокировок с абсолютной уверенностью, вы можете выполнять свои операторы в сериализуемой изоляции транзакций . Но это дороже, и вам нужно подготовиться к повторению команд при сбое сериализации.
Ваш лучший способ действий, вероятно, заключается в том, чтобы явно заблокировать его SELECT ... ORDER BY ... FOR UPDATEв подзапросе или в отдельной SELECTтранзакции - по умолчанию на уровне изоляции «чтение зафиксировано». Цитирую Тома Лейна на pgsql-general :
Все должно быть в порядке - блокировка FOR UPDATE всегда является последним шагом в конвейере SELECT.
Это должно сделать работу:
BEGIN;
SELECT 1
FROM foo
WHERE baz = 1234
ORDER BY bar
FOR UPDATE;
UPDATE foo
SET bar = bar + 1
WHERE baz = 1234;
COMMIT;
Многостолбцовый индекс (baz, bar)может быть идеальным для производительности. Но так barкак он, очевидно, обновлен очень сильно , индекс в одну колонку (baz)может быть даже лучше. Зависит от пары факторов. Сколько строк в baz? Возможны ли горячие обновления без многоколоночного индекса? ...
Если baz он обновляется одновременно, маловероятно, что в случае конфликта возникнет угроза (согласно документации) :
Для SELECTкоманды, работающей на READ COMMITTED
уровне изоляции транзакции, можно использовать ORDER BYпредложение блокировки и вернуть строки не по порядку. ...
Кроме того , если вы должны иметь уникальное ограничение с участием bar, рассмотрим DEFERRABLEограничение , чтобы избежать уникальных нарушений в одной и той же команды. Связанный ответ:
CREATE TABLEкод.