UPDATE堆表 - RID

时间:2016-10-14 13:46:48

标签: 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';

ROLLBACK TRANSACTION

交易2:

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中第二次更新事务1时,将被视为死锁受害者,从而导致事务2&的回滚。完成交易1。

有人可以解释为什么第二个交易需要对同一个RID进行更新锁定,尽管更新了不同的记录吗?

1 个答案:

答案 0 :(得分:2)

  

有人可以解释为什么第二个交易需要对同一个RID进行更新锁定,尽管更新了不同的记录吗?

这可以改为:当没有索引时,Update语句如何获取需要更新的表上的锁..

SQL在页面上采用意图独占锁定,然后在读取之前尝试对页面的行进行U锁定,如果它与要更新的值匹配,则此锁定将转换为X锁定。

这个U锁策略是为了确保不会在同一行上采取其他不兼容的锁

请参阅Kalen Delaney的以下链接,了解相同的详细信息

http://sqlblog.com/blogs/kalen_delaney/archive/2009/11/13/update-locks.aspx