Sql server 事务隔离级别可重复读取导致死锁

Sql server 事务隔离级别可重复读取导致死锁,sql-server,transactions,Sql Server,Transactions,在事务隔离级别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 t

在事务隔离级别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.
我认为我能够使用以下示例重新生成问题

一,

二,

三,

启动隔离级别为可重复读取的长事务

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
四,

当上述步骤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中,我有哪些选项可以最终运行事务。其思想是能够将记录重置为默认值,在这种情况下,对其他事务执行的任何操作都应该被覆盖。如果两个事务都不是并发的,我看不出有任何问题。

您可以在SETP4中设置事务的死锁优先级更高 有关更多详细信息,请参阅

其想法是能够将记录重置为默认值

您希望以什么顺序应用更新?你想让“重置”总是通过吗?然后,您需要在步骤3中的更新完成后严格执行重置。此外,重置更新应使用更高的锁定模式以避免死锁:

update accounts WITH (XLOCK)
set Amount = 5000
where id = 1
这样,重置将等待另一个事务首先完成,因为另一个事务具有S锁


或者,第3步获得U型锁或X型锁。

这将使第4步成功,但杀死另一个tran。谢谢,这正是我想要的。我试过你的建议,它似乎是按照要求工作。我不确定我是否理解XLOCK在这里做什么。我阅读了文档,但无法与此场景关联。XLOCK使查询获取独占锁,而不是U锁。您不希望锁与步骤3兼容,因此步骤4必须等待步骤3完成。谢谢,非常感谢您的帮助!刚刚认识到一件事,如果只将步骤3的事务隔离级别更改为“SERIALIZABLE”,则在步骤4事务等待IX请求模式时,它将被授予X锁(如sys.dm_tran_locks中所示)。这样,步骤3完成,然后步骤4继续。您在步骤3中看到的X锁只能来自(完成的)update语句,因为serializable不会导致X锁,而以前只有S锁发生。Serializable实际上只会导致更多的S锁,并导致这些锁被保留的时间更长。顺便说一句,在示例中添加
id
上的聚集索引,以便使用行锁定。现在您可能会看到来自表锁定的工件(表是一个必须始终扫描的堆)。因此
Account
table是一个没有任何非聚集索引的堆?对于这个re-pro示例,它是一个堆,但我必须检查实际的表。这有关系吗?当然。它关系到每一个指数。请添加帐户表上所有索引的列表。感谢@BogdanSahlean让我检查相关表上的索引。
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.
update accounts WITH (XLOCK)
set Amount = 5000
where id = 1