web-dev-qa-db-ja.com

選択クエリのトランザクションデッドロック

時々、Selectクエリのみであるストアドプロシージャに対して次のエラーが発生します:Transaction (Process ID 91) was deadlocked on lock

私の最初の理解は、選択クエリがテーブルをロックしないか、クエリしようとするテーブルが別のプロセスによって更新/ロックされていてもデッドロックを引き起こさないことでしたが、選択クエリはデッドロックを引き起こす可能性があるようです上手。

クエリに対してコミットされていない読み取りに分離レベルを設定すると、問題は解決しますか?

27
peanut

私の最初の理解は、選択クエリがテーブルをロックしない、またはデッドロックを引き起こさないということです

この理解は間違っています。 SELECTクエリは、分析する行に共有ロックをかけます。共有ロックは、更新/削除/挿入ステートメントからの排他ロックと競合する可能性があります。 2つのSELECTステートメントはデッドロックしませんが、SELECTはUPDATEでデッドロックする可能性があります。このようなデッドロックが発生すると、SELECTは更新を実行しなかったため、通常は被害者となり、常に引き分けが失われます。

デッドロックと同様に、関係するテーブルの正確なスキーマ、正確なT-SQLステートメント、およびデッドロックグラフをポストする必要があります。 方法:デッドロックグラフを保存する(SQL Server Profiler) を参照してください。この情報を使用して、デッドロックを修正する方法のガイダンスを受け取ることができます。

43
Remus Rusanu

Remusが言うように、SELECTとSELECTではなくSELECTとUPDATE(または他の)操作がお互いにデッドロックするため、デッドロックが発生します。そのテーブルに関連するすべてのクエリを確認し、それらのクエリに適切なカバリングインデックスを作成する必要があります。これにより問題が解決します。 WITH(NOLOCK)テーブルヒントを使用するよりも、適切なカバリングインデックスが推奨されるソリューションです。

カバリングインデックスの作成方法とデッドロックへの影響についての適切なチュートリアルについては、次の link を参照してください。

6
Ghlouw

SQL Server 2008を使用している場合は、分離レベルをコミットされていない読み取りに設定して、デッドロックを防ぐことができます。これを見てください link 。コミットされていない、またはWITH(NOLOCK)を読み取る場合、クエリによって返されたデータが実際のものではない可能性があることに注意してください。

4
RC_Cleland