41

SQL Server のデッドロックに関するすべてのドキュメントでは、操作 1 がリソース A をロックしてからリソース B にアクセスしようとし、操作 2 がリソース B をロックしてリソース A にアクセスしようとするシナリオについて説明しています。

ただし、一部のビジーなアプリケーションでは、選択と更新の間、または複数の選択の間にデッドロックが発生することがよくあります。デッドロック トレース出力の細かい点のいくつかはかなり理解できないと思いますが、2 つの単一操作の間でデッドロックが発生する原因を理解したいと思います。確かに、選択に読み取りロックがある場合、更新は排他ロックを取得する前に待つ必要があり、その逆も同様ですか?

これは SQL Server 2005 で発生しており、違いがあるとは思いません。

4

5 に答える 5

23

これは、選択によって 2 つの異なるインデックスがロックアウトされ、一方、更新によって同じインデックスが逆の順序でロックアウトされるために発生する可能性があります。最初のインデックスは、アクセスする必要があるすべての列をカバーしていないため、選択には 2 つのインデックスが必要です。インデックスのキー列を更新する場合、ロックを取得する必要があるため、更新には 2 つのインデックスが必要です。

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

于 2009-03-25T14:08:40.910 に答える
14

WITH (UPDLOCK)ロックのヒントについて誰も言及していないことに驚いています。たとえば、2 つの select-insert ペアが並行して実行されているなど、デッドロックが発生している場合に非常に役立ちます。

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

于 2010-06-07T22:57:53.330 に答える
6

私の推測では、選択ステートメントは読み取りロックを取得し、更新ステートメントを使用すると、書き込みロックにアップグレードする必要があります。

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

select-for-update (UPDLOCK) を使用すると、最初から書き込みロックが取得されるため、デッドロックの問題は発生しません。

于 2010-06-18T12:00:02.093 に答える
5

単一のクエリ間のロックは、テーブル全体ではなく単一の行をロックするときに発生する可能性があります。

更新クエリはテーブル内のいくつかの行で更新ロックを取得し、選択クエリはテーブル内の他のいくつかの行で読み取りロックを取得します。次に、更新クエリは読み取りロックされた行の更新ロックを取得しようとし、選択クエリは更新ロックされた行の読み取りロックを取得しようとします。

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

于 2009-03-19T12:29:35.027 に答える
1

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

何に問題があるのか​​、または使用している分離レベルがわかりません。しかし、次のことを考慮してください。データベース エンジンは、1 つのトランザクションで読み取りを行う場合、後で書き込みを行うかどうかをどのように判断できるのでしょうか? 高い分離レベルでは、データが後で書き込みに影響を与える可能性があるため、ファントム読み取りから保護するために、読み取りが行われるたびに、おそらくテーブル全体でロックする必要があります。

データが排他的にロックされるまで、データベースを任意の時間待機させますか? 全体の分離レベルと、分離されたトランザクションとして一連の読み取りを不必要に実行しているかどうかを確認してください。ただし、どの程度汚い読み取りを許容できるかを判断するのは必ずしも簡単ではありません...

于 2009-03-19T12:16:00.413 に答える