跟进https://stackoverflow.com/a/16553083/14731...
我知道,为了减少死锁的频率,维护表的组合锁定顺序很重要,这会影响UPDATE
和SELECT
语句[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 UPDATE
、WITH (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的行不存在,就不可能出现死锁。