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 中的更新完成后严格执行重置。另外,reset更新应该使用更高的锁模式来避免死锁:

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

这样重置将等待另一个事务首先完成,因为另一个 tran 具有 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 回答