何もありませんORDER BY
でSQL UPDATE
コマンド。Postgresは任意の順序で行を更新します。
確実なデッドロックを回避するために、シリアライズ可能なトランザクション分離でステートメントを実行できます。しかし、それはより高価であり、シリアル化の失敗時にコマンドを繰り返す準備をする必要があります。
最善の方法は、トランザクションのSELECT ... ORDER BY ... FOR UPDATE
サブクエリまたはスタンドアロンSELECT
で明示的にロックすることです-デフォルトの「コミットされた読み取り」分離レベルで。pgsql-generalでのTom Laneの引用:
大丈夫です--- 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
?あるHOT更新を複数列インデックスなしの可能性は?...
baz
が同時に更新される場合でも、(ドキュメントごとに)競合が発生する可能性はほとんどありません。
ことが可能であるSELECT
コマンドで動作するREAD COMMITTED
トランザクション分離レベルと使用ORDER BY
とロック句は順不同の行を返すこと。...
また、あなたが関与するユニーク制約を持つべきであるならばbar
、検討するDEFERRABLE
制約を同じコマンド内で一意の違反を避けるために。関連する回答:
CREATE TABLE
コードを追加することをお勧めします。