ヒープテーブルの更新-> RIDのデッドロック


8

特定のデッドロックシナリオを証明するためにテストケースを設定しており、何が起こっているのかについての洞察が必要です。ヒープテーブルは、HeapTableと呼ばれています。このテーブルは、2つのトランザクションによって同時に更新されます。

トランザクション1:

BEGIN TRAN

UPDATE HeapTable
SET FirstName = 'Dylan'
WHERE FirstName = 'Ovidiu';

WAITFOR DELAY '00:00:15';

UPDATE HeapTable
SET FirstName = 'Bob'
WHERE FirstName = 'Thierry';

ROLLBACK TRANSACTION

トランザクション2:

BEGIN TRAN

UPDATE HeapTable
SET FirstName = 'Pierre'
WHERE FirstName = 'Michael';

ROLLBACK TRAN

最初にトランザクション1を起動し、その後にトランザクション2を続けます。予想どおり、トランザクション1はいくつかの排他的ロックといくつかの意図的な排他的ロックを要求します。トランザクション2が受信され、同じRIDで更新ロックを要求します。

spid dbid   ObjId       IndId   Type    Resource     Mode   Status
55    5     711673583   0       RID     1:24336:10   X      GRANT
57    5     711673583   0       RID     1:24336:10   U      WAIT

2番目のトランザクションが同じRIDで更新ロックを要求するのを見て驚いたのは、これが単一のレコードを指し、両方の更新ステートメントが異なるデータを処理するためだと思ったからです。代わりに、ページレベルでの競合を予想していました。

トランザクション1の2番目の更新がトランザクション2で開始されると、デッドロックの犠牲者と見なされ、トランザクション2のロールバックとトランザクション1の完了が発生します。

別のレコードを更新しているにもかかわらず、2番目のトランザクションが同じRIDで更新ロックを必要とする理由を誰かが説明してもらえますか?

これを修正する方法を知っています(たとえば、インデックスを使用)。私は修正プログラムを探しているのではなく、ヒープ内の異なるレコードを処理する2つの更新が同じRIDをロックする理由についての説明を実際に探しています。コミットされた読み取り分離を使用しています。テーブルに非クラスター化インデックスはありません。

回答:


18

にインデックスがない場合FirstName、SQL Serverはすべての行をチェックして、それがに該当するかどうかを確認する必要がありUPDATEます。

U一般的なデッドロックシナリオを防ぐために、各行を読み取るときに更新ロックがかかります。共有Sロックを取得できますが、それでもX最初のトランザクションが保持する排他ロックによってブロックされます。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.