在事务隔离级别 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 步中运行事务。这个想法是能够将记录重置为默认值,并且在这种情况下应该覆盖对其他事务执行的任何操作。如果两个事务不是并发的,我看不到任何问题。