問題:
テーブルtable_aとが与えられた場合、が更新さtable_bれるたびに、次のような操作を確実に (かつ同時に) 実行する必要があります。table_a
SELECTからのいくつかの行table_a。- アプリケーション コードで何かを計算します。
UPDATEの行table_b。
このようなことが起こるのを防ぐ必要があります (このシナリオ A と呼びますtable_b) table_a。
worker1から行を取得しますtable_a。table_a更新されます。worker2から行を取得しますtable_a。worker2更新しますtable_b。worker1更新しますtable_b。
しかし、これは問題ありません (これをシナリオ B と呼びます) table_b。
worker1から行を取得しますtable_a。table_a更新されます。worker2から行を取得しますtable_a。worker1更新しますtable_b。worker2更新しますtable_b。
取引:
REPEATABLE READ1 つの解決策は、すべてをトランザクションでラップすることです。次にworker1、 のトランザクションはシナリオ A で失敗し、worker2のトランザクションはシナリオ B で失敗します。シナリオを区別する方法がないため、失敗したトランザクションを再試行するしかありません。
しかし、どちらのシナリオでも無駄です。シナリオ A では、はすでに完全に更新されているworker1ため、 のトランザクションを再試行したくありません。シナリオ B では、正しいことを行っていたので、そもそも のトランザクションをtable_b失敗させたくありません。worker2
行のマーキング:
最初から行の主キーがわかっている場合table_b( :b_id)、各ワーカーに一意の ID がある場合 ( :worker_id)、別のことを試すことができます。markに列を追加し、table_bステップ 1 の前に各ワーカーにこれを実行させます。
UPDATE table_b SET mark = :worker_id WHERE id = :b_id;
WHERE次に、ステップ 3 で句を追加します。
UPDATE table_b SET ... WHERE ... AND mark = :worker_id;
必要worker1に応じて、両方のシナリオでステップ 3 の行を更新しません。
ここで行のマーキングは合理的なアプローチですか? 私が見逃している欠点は何ですか?この問題に対する「標準的な」解決策は何ですか?
明確化:私は PostgreSQL を使用しています。