跟进https://stackoverflow.com/a/16553083/14731 ...
我知道维护表的组合锁定顺序以减少死锁的频率很重要,这会影响UPDATE
和SELECT
语句[1]。但是,是否也适用于只读行?
如果在初始化时填充一行并且没有人再次修改它,那么我们访问它的顺序真的很重要吗?
给出两个事务:T1,T2和两个只读行R1,R2
T1读取R1,然后读取R2 T2读取R2,然后读取R1
即使我使用SERIALIZABLE事务隔离,事务也会死锁吗?
[1]如果事务隔离为REPEATABLE_READ
,则T1 SELECT
为R1,R2而T2 UPDATE
为R2,R1可能会发生死锁。
澄清:这个问题不是特定于RDBMS的。我的印象是没有实现可以在只读行上死锁。如果你有一个反例(对于一个具体的供应商),请发一个答案展示同样多,我会接受它。或者,发布您可以证明的所有具体实现的列表不会死锁(并且最完整的列表将被接受)。
答案 0 :(得分:0)
这个问题不可能回答所有可能的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-lock是一种锁定类型,可能会发生冲突并导致死锁。如果没有ID 10的行,则不会出现死锁。