Sql server 更新堆表-RID上的死锁

Sql server 更新堆表-RID上的死锁,sql-server,deadlock,Sql Server,Deadlock,我正在设置一个测试用例,以证明某个死锁场景,并需要了解发生了什么。 我有一个堆表,通常称为HeapTable。此表由2个模拟事务更新 交易1: BEGIN TRAN UPDATE HeapTable SET FirstName = 'Dylan' WHERE FirstName = 'Ovidiu'; WAITFOR DELAY '00:00:15'; UPDATE HeapTable SET FirstName = 'Bob' WHERE FirstName = 'Thierry';

我正在设置一个测试用例,以证明某个死锁场景,并需要了解发生了什么。 我有一个堆表,通常称为HeapTable。此表由2个模拟事务更新

交易1:

BEGIN TRAN

UPDATE HeapTable
SET FirstName = 'Dylan'
WHERE FirstName = 'Ovidiu';

WAITFOR DELAY '00:00:15';

UPDATE HeapTable
SET FirstName = 'Bob'
WHERE FirstName = 'Thierry';

ROLLBACK TRANSACTION
BEGIN TRAN

UPDATE HeapTable
SET FirstName = 'Pierre'
WHERE FirstName = 'Michael';

ROLLBACK TRAN
交易2:

BEGIN TRAN

UPDATE HeapTable
SET FirstName = 'Dylan'
WHERE FirstName = 'Ovidiu';

WAITFOR DELAY '00:00:15';

UPDATE HeapTable
SET FirstName = 'Bob'
WHERE FirstName = 'Thierry';

ROLLBACK TRANSACTION
BEGIN TRAN

UPDATE HeapTable
SET FirstName = 'Pierre'
WHERE FirstName = 'Michael';

ROLLBACK TRAN
我首先启动事务1,紧接着启动事务2。正如预期的那样,事务1将声明一些排他锁,以及一些意图排他锁。事务2将进入并请求同一RID上的更新锁:

spid dbid   ObjId       IndId   Type    Resource     Mode   Status
55    5     711673583   0       RID     1:24336:10   X      GRANT
57    5     711673583   0       RID     1:24336:10   U      WAIT
看到第二个事务在同一个RID上请求更新锁,我有点惊讶,因为我认为这指向一个记录&两个Update语句处理不同的数据。我不知怎的以为页面级会发生冲突

当事务1的第二次更新启动时,事务2将被视为死锁牺牲品,导致事务2回滚并完成事务1

有人能解释一下为什么第二个事务需要更新同一个RID上的更新锁,尽管更新了不同的记录

有人能解释一下为什么第二个事务需要更新同一个RID上的更新锁,尽管更新了不同的记录

这可以重新表述为,当不存在索引时,Update语句如何在需要更新的表上获取锁

SQL在页上获取一个intent Exclusive锁,然后在读取页之前尝试在页的行上获取U锁,如果它与要更新的值匹配,则该锁将转换为X锁

此U锁策略旨在确保不会在同一行上使用其他不兼容的锁

请参阅卡伦·德莱尼的以下链接,了解关于同一网站的详细信息


这个DBA问题应该在DBA.SE上吗?@ajeh总是发现两者之间的界限有些模糊。如果你认为它在那里更有用的话,我会把它贴在那里。这里很好。不用担心。在DBA.SE上,您会得到专业DBA的更多关注,这里有更多的开发人员。这最终取决于你的个人偏好,但我相信你可以从那些每天关注这些问题的人那里得到更多的关注。因此,如果我理解正确,第二次交易将尝试获取页面中所有记录的更新锁,只是尝试找到它真正需要的记录?是的,当没有索引时,它必须扫描每一条记录,以找出感谢您为我澄清了这一点,并加深了我对这一点的了解。你太棒了!