4

アプリケーションの一部は、トランザクション分離レベル REPEATABLE READ で接続を開いた後、ビジネス ロジックに従ってテーブルを更新します。まれに、この操作が別の接続を開き、同じレコードをデフォルト値にリセットしようとするアプリケーションの別の部分と一致する場合があります。次のエラーが表示されます

Msg 1205, Level 13, State 45, Line 7
Transaction (Process ID 60) was deadlocked on lock resources with another process and has been chosen as the deadlock victim. Rerun the transaction.

次の例を使用して問題を再現できると思います。

1.

create table Accounts
(
id int identity(1,1),
Name varchar(50),
Amount decimal
)

2.

insert into Accounts (Name,Amount) values ('ABC',5000)
insert into Accounts (Name,Amount) values ('WXY',4000)
insert into Accounts (Name,Amount) values ('XYZ',4500)

3.

分離レベルが REPEATABLE READ のロング トランザクションを開始する

Set transaction isolation level REPEATABLE READ

begin tran

declare @var int

select @var=amount 
from Accounts
where id=1

waitfor delay '0:0:10'

if @var > 4000

update accounts 
set amount = amount -100;

Commit

4.

上記の Step.3 がまだ実行されている間。別の接続で別のトランザクションを開始する

Begin tran

update accounts
set Amount = 5000
where id = 1

commit tran

ステップ 3 で開始されたトランザクションは最終的に完了しますが、ステップ 4 で開始されたトランザクションは失敗し、次のエラー メッセージが表示されます。

Msg 1205, Level 13, State 45, Line 7
Transaction (Process ID 60) was deadlocked on lock resources with another process and has been chosen as the deadlock victim. Rerun the transaction.

ステップ4で最終的にトランザクションを実行できるようにするためのオプションは何ですか。アイデアは、レコードをデフォルト値にリセットできるようにすることであり、この場合、他のトランザクションで実行されているものはすべてオーバーライドする必要があります。両方のトランザクションが同時でない場合、問題はありません。

4

2 に答える 2

4

アイデアは、レコードをデフォルト値にリセットできるようにすることです

アップデートを適用する順序を教えてください。「リセット」が常に行われるようにしますか? 次に、手順 3 の更新が完了した後、厳密にリセットを実行する必要があります。また、リセット更新では、デッドロックを回避するために、より高いロック モードを使用する必要があります。

update accounts WITH (XLOCK)
set Amount = 5000
where id = 1

そうすれば、リセットは他のトランザクションが最初に終了するのを待ちます。これは、他のトランザクションに S ロックがあるためです。

または、手順 3 で U ロックまたは X ロックを取得します。

于 2013-09-01T11:15:35.877 に答える
0

setp 4 でトランザクションのデッドロック優先度を高く設定できます。詳細については、http: //technet.microsoft.com/en-us/library/ms186736.aspx を参照してください。

于 2013-09-01T11:10:44.593 に答える