2012-01-17 24 views
3

デッドロックが多く読んでいて、ここでよく分かっていると思ったときに問題が発生します。1つのテーブルで2つの異なる行を更新しているときのデッドロック

同時に2つの同様のトランザクションが行われます。彼らは、以下のようになります。

BEGIN TRAN //read_committed_snapshot ON 

//an application sends insert query 
INSERT INTO t1 VALUES('Name',15) 

//later on application sends update query for the newly inserted row 
UPDATE t1 SET name='NewName', number=16 WHERE id = 10 //this ID is the id of the inserted row. 

COMMIT 

は、与えられたコードは、私は私のアプリで使用し、正確なものではないが、アイデアは、それだけでより多くの列があり、同じです。

表t1には、プライマリ・キーIDと非クラスタ化インデックスがあります。

これらのトランザクションのうち2つを同時に実行すると、デッドロックが発生します。プロファイラは、デッドロックされたクエリは、矛盾するプロセスごとにUPDATE t1 SET name='NewName', number=16 WHERE id = :idであったと報告しています。

私はデッドロックのXMLを持っていませんが、プロファイラは両方のプロセスにXロックがあり、両方がUロックを取得しようとしていることを伝えました。

process 1 
owner - X 
waiter - U 

process 2 
owner - X 
waiter - U 
t1

テーブルはindexnameとしてオブジェクトとPK_id指標として両方のプロセスについて示されました。

ここで実際に何が起こっていますか?各トランザクションは同じテーブル内の異なる行を更新しますが、なぜデッドロックですか?

多くの例では、「インデックスをスキャンする方法、1つのトランザクションのpkインデックスと別のトランザクションの他の非クラスタ化インデックスをスキャンしているので、indexnameの下に異なるプロファイラーデッドロックグラフが表示されます。私が持っているのと同じではなく、インデックスの名前は同じです。

これを解決する方法はありますか?それは私を夢中にさせる。私はread_committed_snapshotを有効にするとこれを解決できると思ったが、私は間違っていた。

答えて

3

ほとんどの場合、テーブル/クラスタ化インデックスを使用して更新の1つまたは両方が更新のための行を見つけるためにスキャンをスキャンします - デッドロックが発生することがよくあります。実行計画を確認してください。

+0

しかし、排他的なロックをすでに取得しています。これは、更新される行のキーロックがわかります。問題の2つの行以外のものに更新ロックを設定しようとするとどうなるでしょうか。私は実行計画をチェックします(私はまだ簡単にそこに紛失してしまいます) – user1651105

+0

テーブルとページにインテントロックがあり、テーブルにはインデックスがあるため、インデックスの更新にもクエリが干渉することがあります –

関連する問題