アプリケーションでブックマーク ルックアップのデッドロックが検出されました。使用する解決策を決定できません。それらのどれも最適ではないようです。
クエリは次のとおりです。
UPDATE TEST SET DATA = @data WHERE CATEGORY = @cat
SELECT DATA, EXTRA_COLUMN FROM TEST WHERE CATEGORY = @cat
問題は、クラスター化インデックスと逆の順序で両方のクエリで使用される CATEGORY と DATA に非クラスター化インデックスがあることです。
つまり、更新はクラスター化インデックスをロックしてテーブルを更新しますが、選択はクラスター化されていないインデックスをロックしてブックマークの検索を行い、両方がお互いにロックすることを望んでいます (デッドロック)。
私が見つけたオプションは次のとおりです。
1 - 選択クエリのすべての列を含むインデックスを作成します。- うまくいきましたが、良い考えだとは思いません。アプリケーションのどこでも更新できる選択クエリで使用される列を含める必要があります。
2 - データベースのトランザクション分離レベルを COMMITTED_SNAPSHOT に変更します
3 - 選択に NOLOCK ヒントを追加します
4 - インデックスを削除する
5 - 他のトランザクションをブロックすることになるロックを取得する機会が得られる前に、トランザクションの 1 つを早い時点で強制的にブロックします。(動作しませんでした)
2 番目のオプションが最良の選択だと思いますが、他の問題が発生する可能性があることはわかっています。COMMITTED_SNAPSHOT を SQL SERVER の既定の分離レベルにするべきではありませんか?
アプリケーションにもデータベース ロジックにもエラーはないように思えます。これは、非クラスター化インデックスを持つ 1 つの単純なテーブルと、同じテーブルにアクセスする 2 つのクエリ (1 つは更新用、もう 1 つは選択用) です。
この問題を解決する最良の方法はどれですか? 他の解決策はありますか?
SQL Server が単独で解決できることを本当に期待していました。