Нет 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
код.