次のことを行う複数のスレッドから呼び出されるプロセスがあります。
- 取引開始
IsProcessed=0
ヒントのある次の行を見つけて、作業テーブルから作業単位を選択します(UPDLOCK, HOLDLOCK, READPAST)
- 作業単位を処理する (C# および SQL ストアド プロシージャ)
- トランザクションをコミットする
これの考え方は、スレッドが「次の」作業のためにプールに浸り、それを処理し、1 つの作業が 2 回処理されないようにするためにロックが存在するというものです。(順番は関係ありません)。
これらすべてが何ヶ月もうまく機能しています。今日まで、つまり、スナップショット分離を有効にしてデータベース レベルでデフォルトに設定しているにもかかわらず、実際のトランザクション作成コードは手動で "ReadCommitted" の分離レベルを設定していたことに気付きました。
私はそれを「スナップショット」に正式に変更し、もちろんすぐに以下のメッセージを受け取りました:
READ COMMITTED または REPEATABLE READ では、READPAST ロックのみを指定できます。
行をロックする主な理由は、マークを適用したトランザクションがコミットされたときに「マーク」が削除されるように「行にマークを付ける」ことであり、ロックはこれを行うための最良の方法であると思われました。テーブルは、これらのスレッド以外では読み取られません。IsProcessed フラグをロックとして使用する場合、おそらく最初に更新を行ってから、更新したばかりの行を選択する必要がありますが、NOLOCK フラグを使用して、他のスレッドが設定したかどうかを知る必要があります。旗が並んでいます。
すべてが少し乱雑に聞こえます。最も簡単なオプションは、スナップショット分離モードを完全に放棄することですが、ステップ #3 の設計ではそれが必要です。
この問題を解決する最善の方法について何か素晴らしいアイデアはありますか?