阅读this有趣的文章后,我有一些问题。
此表显示死锁情况:
T1保持对表t_lock1上c1 = 5的所有行的X锁定 X锁定表t_lock2上C1 = 1的所有行。
现在,这些事务中的每一个都想要先更新行 被另一方锁定。这会导致死锁。
问题#1
所以从这个例子看来,事务也持有一个锁....它是否正确?
问题#2
... T1在表t_lock1 ...
上对c1 = 5的所有行保持X锁定
答案 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)
交易是否获得锁定?
没有。您执行的语句 - SELECT
或UPDATE
将获取锁。根据您的事务隔离级别设置,(共享)锁定(读取SELECT
)的持续时间会有所不同 - 这就是全部。共享锁通常只是非常简短地保存,而更新和排它锁保持到事务结束。事务可能持有锁 - 但它不获取锁的事务......
* ... T1对表t_lock1 ... *
上的c1 = 5的所有行保持X锁定 恕我直言,因为我已经说过锁定不是每行(尽管可以制作,但是作者没有提到它)所以为什么他说:在C1 = 5的所有行上? < / p>
默认情况下,每行锁定 。但为什么你认为C1=5
只有一行?可能存在多个 - 可能是数千个 - 而UPDATE
语句将通过UPDATE
语句锁定所有受影响的行。