4

大きなテーブルを更新しようとしているのですが、ロックについて心配する必要があるかどうか疑問に思っています。

次のようなテーブルがあります。

CREATE TABLE "ItemsToProcess"( 
"id" text, 
"WorkerInstanceId" text, 
"ProcessingStartTime" timestamp with time zone, 
"UpdatedTime" timestamp with time zone, 
CONSTRAINT "ITP_PK" PRIMARY KEY ("id")
)WITH (
  OIDS=FALSE
);

当初、このテーブルには約 200 万行があり、id列のみが入力されていますWorkerInstanceId。2 つのタイムスタンプはNULL、デフォルトで実行開始時のものです。

何が起こるかというと、一部のワーカー アプリ (少なくとも 2 つですが、本番環境では約 10 ~ 13 になる予定です) が、このテーブルから ID のバッチ (batchSize を 200 に設定する予定です) をマークして処理できるようにします。処理中に何が起こるかは、今ではあまり重要ではありません。

バッチのマーキングは次のようになります。

UPDATE "ItemsToProcess" 
   SET "WorkerInstanceId" = ?, "ProcessingStartTime" = current_timestamp()
 WHERE "WorkerInstanceId" is NULL
 LIMIT 200;

私の質問は、更新を行う前に、更新しようとしている行をロックすることについて心配する必要がありますか?

Postgre のドキュメントには次のように書かれています。

行排他

SHARE、SHARE ROW EXCLUSIVE、EXCLUSIVE、および ACCESS EXCLUSIVE ロック モードと競合します。

コマンド UPDATE、DELETE、および INSERT は、(他の参照テーブルに対する ACCESS SHARE ロックに加えて) ターゲット テーブルでこのロック モードを取得します。一般に、このロック モードは、テーブル内のデータを変更するコマンドによって取得されます。

したがって、ワーカーの 1 人がこの更新を行うたびに、テーブル全体がロックされ、200 行が更新され、最終的にロックが解放されると思います。ロックが設定されるまで、他のワーカーはロックが解放されるのを待ちます。これは正しいですか、それとも何か不足していますか?

4

2 に答える 2

8

UPDATE行をロックするため、最初にロックする必要はありません。UPDATE行のセットを同時にオーバーラップしようとすると、2番目UPDATEは最初のトランザクションがコミットまたはロールバックするのを待ちます。

UPDATE句がないという事実を除いて、あなたのアプローチの大きな問題LIMITは、複数のワーカーがすべて同じ行を取得しようとすることです。何が起こるかです:

  • worker1:テーブルをフィルタリングして200行を検索し、それらをロックします
  • worker1:行の更新を開始します
  • worker2:テーブルをフィルタリングして200行を検索します
  • worker2:行の更新を開始しようとしましたが、worker1と同じ行を選択したため、worker1のロックをブロックします
  • worker1:行の更新を終了します
  • worker2:ロック解除後、WHERE条件を再チェックし、worker1が行を更新したため、どの行も一致しなくなったことを確認します。ゼロ行を更新します。

...そして繰り返します!

次のいずれかを行う必要があります。

  • 適切な並行性に安全な方法で行を配布する中央キューを用意します。また
  • 作業するIDの重複しない範囲をワーカーに割り当てます

LIMIT-使用することもできます-ですWHERE id IN (SELECT t.id FROM thetable t LIMIT 200 ORDER BY id)が、両方のワーカーが同じ行のセットを選択して更新する場合にも同じ問題が発生します。

于 2012-08-01T23:34:14.187 に答える
2

あなたはいくつかのことを見逃しています。

LIMITまず、PostgreSQLは更新のオプションを提供していません。UPDATEのドキュメントを参照してください。

ROW EXCLUSIVE第二に、それ自体と競合しないことに注意してください、SHARE ROW EXCLUSIVEそれは異なるものと競合します。したがって、UPDATEステートメントは複数のワーカーから同時に安全に実行できます。それでも、更新時間を短くする必要があります。ただし、問題が発生した場合は、値を下げることで調整する方法がすでに組み込まれていますbatchSize

于 2012-08-01T14:55:14.187 に答える