2009-03-19 26 views
32

SQL Serverのデッドロックに関するすべてのドキュメントでは、操作1がリソースAをロックし、次にリソースBにアクセスしようとし、操作2がリソースBをロックしてリソースAにアクセスしようとします選択/更新または複数選択間のSQL Serverデッドロック

しかし私は頻繁に選択と更新の間、または複数の選択間でデッドロックを見ます。私はデッドロックトレース出力の細かい点のいくつかがかなり侵入不可能であることを知っていますが、私は実際には2つの単一の操作の間にデッドロックを引き起こす原因を理解したいと思います。確かにselectに読み取りロックがある場合、更新は排他ロックを取得する前に待機する必要がありますか?

これはSQL Server 2005では起こっていますが、これは違いがないと思います。

答えて

11

を私は一度SQL-Server-Performance.comでAdvanced SQL Server lockingについての良い記事をブックマーク。その記事はあなたが言及した古典的なデッドロックの状況を超えて、あなたの問題についていくつかの洞察を与えるかもしれません。

0

あなたはトランザクションの分離をよく読んべき: http://msdn.microsoft.com/en-us/library/ms173763.aspx

+0

私は分離レベルについて理解していますが、上記のデッドロックはselectを非コミットにすることで解決できますが、なぜ更新が読み込みコミットを使用してそのデッドロックで終了するのはなぜですか? –

1

トランザクションと分離レベルについては、適切に読み上げてください。いくらか高密度ですが、かなり徹底的で技術的に中立的な作業については、Principles of Transaction Processingを参照してください。それは私の世界を揺るがしました(私にはかなりの頭痛を与えました!)。

あなたは何が問題になっているのか、あなたが使っている分離レベルはわかりません。しかし、これを考慮してください:データベースエンジンがすべて知っているので、あるトランザクションで読み込みを行うと、後で書き込みを行うかどうかをどのように判断できますか?高い隔離レベルは、データが後で書き込みに影響を与える可能性があるため、読み込みが完了するたびにロックを必要とします。

データを排他的にロックするためにデータベースを任意に長く待機させますか?あなたの独立性レベルを一貫して見て、不必要に一連の読み取りを孤立したトランザクションとして実行しているかどうかを確認してください。

を更新クエリは、上の更新ロックを取得します。それは、彼らは、単一の行ではなく、テーブル全体をロックするようけれども...単一のクエリの間

+2

私はポスターの質問は、孤立したレベルの一般的な暴言よりも具体的であると思います。 – eckes

+0

私はPoTPを暴言として正確には特定できません。 Robは具体的にトランザクション性の理解を助けてくれるよう頼んだり、関連するトレードオフを理解するのに苦労していたようだ。有用な文献を指摘すれば、私はおそらく口の中で常に泡立つでしょう! YMMV。 –

5

ロックが発生する可能性があり、あなたは耐えることができるか不潔読み込みを決定することは必ずしも容易ではありませんテーブル内にいくつかの行があり、selectクエリはテーブル内の他のいくつかの行に対して読み取りロックを取得します。更新クエリは、ロックされた行に対して更新ロックを取得しようとします。選択クエリは、更新がロックされている行に対して読み取りロックを取得しようとします。

エスカレートするロックではさらに複雑になります。つまり、データベースはトランザクションによってロックされた1行が多すぎると判断して、テーブルのセクションまたはテーブル全体をロックするようにエスカレートする必要があります。これは、ロックがクエリに直接関係していない行に影響する可能性があることを意味します。

19

これは、selectが2つの異なるインデックスに対してロックアウトを行い、更新が同じインデックスに対して逆の順序でロックアウトするために発生します。 selectには2つのインデックスが必要です。なぜなら、最初のインデックスはアクセスする必要があるすべてのカラムをカバーしていないからです。更新プログラムには2つのインデックスが必要です。なぜなら、インデックスのキー列を更新すると、そのインデックスをロックする必要があるからです。

http://blogs.msdn.com/bartd/archive/2006/09/25/770928.aspxは素晴らしい説明があります。推奨される修正には、選択に必要なすべての列をカバーするインデックスの追加、スナップショットの分離への切り替え、または通常は必要のない更新ロックの取得を明示的に強制することが含まれます。

12

ロックヒントWITH (UPDLOCK)は誰も言及していないことに驚いています。たとえば、デッドロックが発生した場合などに便利です。 2つの選択 - 挿入ペアが並行して実行される。

SQL Serverでは、WITH (UPDLOCK)で選択を発行すると、2番目の選択は最初の選択が完了するまで待機します。それ以外の場合、共有ロックが取得され、同時に排他ロックにアップグレードしようとするとデッドロックになります。

+0

'Rolf Kristensen'は彼の答えに完全にWITH(UPDLOCK)を説明しました。 – Mahmoodvcs

4

私は、select-statementがread-lockを受け取り、update-statementが来たら、それを書き込みロックにアップグレードする必要があると思います。

書き込みロックにアップグレードするには、他のすべての読み取りロックが削除されている必要があります(その選択トランザクションは完了します)。しかし、別のプロセスが書き込みロックにアップグレードするという素晴らしいアイデアをすでに持っている場合、2つのプロセスが突然読み取りロックを解放するのを待っているので、書き込みロックを得ることができます。

select-for-update(UPDLOCK)を使用している場合は、最初から書き込みロックを受け取り、デッドロックの問題は発生しません。

関連する問題