只读行是否会触发数据库死锁



跟进https://stackoverflow.com/a/16553083/14731...

我知道,为了减少死锁的频率,维护表的组合锁定顺序很重要,这会影响UPDATESELECT语句[1]。但是,只读行也是如此吗

如果一行在初始化时被填充一次,而没有人再修改它,那么我们访问它的顺序真的重要吗?

给定两个事务:T1、T2和两个只读行R1、R2

T1读取R1,然后读取R2T2读取R2,然后R1读取

即使我使用SERIALIZABLE事务隔离,事务是否会死锁?

[1] 如果事务隔离是REPEATABLE_READ,T1 SELECT s R1,R2,而T2 UPDATE s R2,R1,则可能发生死锁。

澄清:这个问题不是特定于RDBMS的。我的印象是,任何实现都不能在只读行上死锁。如果你有一个反例(针对具体的供应商),请发布一个答案来证明这一点,我会接受。或者,发布一个你可以证明不会死锁的所有具体实现的列表(最完整的列表会被接受)。

这个问题不可能回答所有可能的RDBMS,因为锁定策略是一个实现细节。也就是说,有用的RDBMS将共享一些共同的特性:

对于没有应用提示的SELECT语句(FOR UPDATEWITH (UPDLOCK)…),任何合理的RDBMS都不会使用写锁。可能需要读锁。事实上,除了Hekaton表之外,至少SQL Server对SERIALIZABLE是这样做的。

读取锁从不冲突如果只执行读取,则不可能出现死锁

但是,只读行即使从未写入,也会导致死锁。在SQL Server中,

UPDATE T SET SomeCol = 1 WHERE ID = 10 AND SomeCol = 0

将在ID为10的行上使用U形锁。如果SomeCol不为0,则锁将立即释放,并且不会写入任何内容。但U型锁是一种可能发生冲突并导致死锁的锁类型。如果ID为10的行不存在,就不可能出现死锁。

最新更新