データベースを使用してクライアントを同期する分散アプリケーションがあります。クライアントはレコードを更新しようとしますが、過去 1 時間に他のクライアントが更新を行っていない場合にのみ更新を行います。
縮小されたコードとジレンマは次のとおりです。
あるクライアントがフィールドを「赤」に更新しようとしたとします (過去 1 時間以内に他の誰も更新していないことを確認します)。
UPDATE mytesttable
SET Status = 'Red',
TimeOfLastUpdate = sysdate
WHERE TimeOfLastUpdate < sysdate-1/24
同時に、別のクライアントがそれを「緑」に更新しようとします (過去 1 時間以内に他の誰も更新していないことを確認します)。
UPDATE mytesttable
SET Status = 'Green',
TimeOfLastUpdate = sysdate
WHERE TimeOfLastUpdate < sysdate-1/24
行の更新に成功するクライアントは1 つだけであると想定できますか?
答えが「いいえ」だと思う理由は次のとおりです。
Oracleは行レベルの更新ロックを取得するsysdate
前に解決する必要があるため (最初に行を見つけるためにそれを使用する必要があるため)、競合状態があるように見えます。
- クライアント「レッド」が計算
sysdate
- クライアント「グリーン」が計算
sysdate
- 1時間経過
- クライアント「赤」
TimeOfLastUpdate
が古いもので更新sysdate
- クライアント「グリーン」
TimeOfLastUpdate
は古いもので更新されますsysdate
(したがって、2回更新されます)
これを競合状態として特定するのは正しいですか? そうでない場合、何が欠けていますか?
もしそうなら、この問題に対する効率的で信頼性の高い解決策はありますか?