1

最近、デッドロックの問題が発生しました。システムの2つの部分が同じ時間に同じテーブルを更新します。1つはトランザクション内の複数の行を更新(「UP1」と名付け)、もう1つ(「UP2」と名付け)は「update ...whereid」のようなSQLを使用します。の (...)"。

これは、sql "update ... where id in(...)"のIDの順序が正しくないためと思われます(例: "5,6,2,3,4,1")。トランザクションでは、更新アクションは「1,2,3,4,5,6」の順序で動作します。「UP1」がID「1,2,3,4」と「UP2」更新ID「5,6」を更新する場合、「UP1」は「UP2」と「UP2」によってロックされているID5を必要とします。 「UP1」によってロックされているID2が必要なので、デッドロックが発生します。

私の質問は、dbは行を1つずつロックし、SQLまたはトランザクションが完了したときにのみそれらを解放するのですか?そうでない場合、トランザクションの開始時または「where id in(...)」SQLですべての行をロックできないのはなぜですか。また、更新された行を1つずつ解放できないのはなぜですか。

役立つ返信をお待ちしております、thx。

4

1 に答える 1

1

あなたはほぼ正しい方向に進んでいます。デフォルトのReadCommittedIsolation Levelを使用すると、PostgreSQLは途中でロックを取得し、トランザクションがコミットまたはロールバックされたときにそれらを解放します。

すべてのUPDATE操作が同じ順序で行を更新することを確認できれば、デッドロックに遭遇することはありません。UP1更新行を昇順で作成し、同じ方法でINリストを並べ替えようとしましたか?UP2

同期された更新を保証できない場合は、SerializableIsolationLevelに関心があるかもしれません。これは最も厳密な分離レベルであり、特に同時実行性が高い場合は、クエリの速度が少し低下する可能性があります。しかし、それはあなたが見るエラーを防ぐはずです。また、シリアル化の失敗が原因でトランザクションを再試行する準備をしてください。

このために、次のコマンドでトランザクションを開始します。

BEGIN ISOLATION LEVEL SERIALIZABLE;
于 2012-07-12T19:30:29.273 に答える