3

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

下表显示了死锁情况:

在此处输入图像描述

T1 在表 t_lock1 上对所有 c1=5 的行持有 X 锁,而 T2 在表 t_lock2 上对所有 C1=1 的行持有 X 锁。

现在这些事务中的每一个都希望更新先前被另一个锁定的行。这会导致死锁。

问题 #1

  • 事务是否获得锁?我知道从表中读取是通过共享锁完成的,而对表的写入是使用排他锁完成的(我说的是默认锁定设置)。

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

问题2

...T1 对表 t_lock1 上 c1=5 的所有行持有 X 锁...

  • 恕我直言,正如我所说,锁定不是每行(尽管可以进行,但作者没有提到) - 那么他为什么说:在所有行上 C1=5
4

2 回答 2

1

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

由于您的查询中没有选择,因此只使用 U 和 X 锁。对正在更新的表的更新查询不采用 S 锁。这是一种启发式死锁避免方案。

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

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

于 2012-09-03T20:36:11.807 回答
1

事务是否获得锁?

不。您执行的语句 - aSELECT或 anUPDATE将获取锁。根据您的事务隔离级别设置,(共享)锁定(用于读取SELECT)将保持多长时间的持续时间会有所不同 - 仅此而已。共享锁通常只持有非常短暂的时间,而更新锁和排他锁会一直持有到事务结束。事务可能持有锁 - 但获取锁的不是事务......

*...T1 对表 t_lock1 上 c1=5 的所有行持有 X 锁...*
恕我直言,我说过锁定不是每行(虽然可以进行,但作者没有提到它)那么他为什么说:在所有 C1=5 的行上?

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

于 2012-09-04T00:53:22.793 回答