SQL Server死锁清晰度?

时间:2012-09-03 20:29:03

标签: sql-server sql-server-2005 deadlock

阅读this有趣的文章后,我有一些问题。

此表显示死锁情况:

enter image description here

  

T1保持对表t_lock1上c1 = 5的所有行的X锁定   X锁定表t_lock2上C1 = 1的所有行。

     

现在,这些事务中的每一个都想要先更新行   被另一方锁定。这会导致死锁。

问题#1

  • 交易是否获得锁定?我知道表中的读取是由共享锁完成的,到表是使用独占 lock(我在谈论默认锁定设置)。

所以从这个例子看来,事务持有一个锁....它是否正确?

问题#2

  

... T1在表t_lock1 ...

上对c1 = 5的所有行保持X锁定
  • 恕我直言,因为我已经说过锁定不是每行(尽管可以制作,但是作者没有提到它) - 所以为什么他说:在所有行上C1 = 5

2 个答案:

答案 0 :(得分:1)

对于问题1:SQL Server使用U-lock读取源表行,然后更新它们,仅在那些符合更新条件的行上将它们转换为X-locks。注意读取多行,然后将它们过滤到写入的行之间的区别。这两组锁定不同。

由于查询中没有选择,因此只会执行U和X锁定。正在更新的表上不会对更新查询进行S锁定。这是一种启发式的死锁避免方案。

问题2:锁定可以以不同的粒度进行,但对于低行数,通常是每行(这可以强制)。也许作者假设C1上的索引,这意味着只需要读取和锁定C1 = 1的行。所有其他行都不会被触及。

如果没有索引,SQL Server确实会读取表的所有行,在执行此操作时将其锁定,然后对那些满足C1 = 1的行进行X锁定。作者确实提到只有C1 = 1的行被x锁定。

答案 1 :(得分:1)

  

交易是否获得锁定?

没有。您执行的语句 - SELECTUPDATE将获取锁。根据您的事务隔离级别设置,(共享)锁定(读取SELECT)的持续时间会有所不同 - 这就是全部。共享锁通常只是非常简短地保存,而更新和排它锁保持到事务结束。事务可能持有锁 - 但它获取锁的事务......

  

* ... T1对表t_lock1 ... *
上的c1 = 5的所有行保持X锁定   恕我直言,因为我已经说过锁定不是每行(尽管可以制作,但是作者没有提到它)所以为什么他说:在C1 = 5的所有行上? < / p>

默认情况下,每行锁定 。但为什么你认为C1=5只有一行?可能存在多个 - 可能是数千个 - 而UPDATE语句将通过UPDATE语句锁定所有受影响的行