使用 MySQL 隔离级别 Repeatable Read。
给定表 test
具有非索引列 quantity
:
id | quantity
--------------------
1 | 10
2 | 20
3 | 30
Tx1 执行 1st,注意它还没有提交,意味着所有获取的锁还没有释放。
TX1:
START TRANSACTION;
DELETE FROM test WHERE quantity=10;
现在执行Tx2
TX2:
START TRANSACTION;
INSERT INTO test(quantity) VALUES (40);
COMMIT;
对于 Tx2,我得到以下结果:
Lock wait timeout exceeded; try restarting transaction
据我了解,作为 quantity
列未编入索引,delete
语句进行全表扫描,锁定所有行(无论 where
条件匹配与否),并且还在聚集索引中的最后一个索引记录之前和之后应用间隙锁,从而导致完全阻塞的表insert
来自 tx2 的语句无法为要插入的行获取锁。
来自 MySQL manual (对于可重复读取隔离级别):
For a unique index with a unique search condition, InnoDB locks only the index record found, not the gap before it.
For other search conditions, InnoDB locks the index range scanned, using gap locks or next-key locks to block insertions by other sessions into the gaps covered by the range (this is used in my case).
考虑到应用任何给定隔离级别的锁定以防止 phenomenas
我有点困惑在这种情况下阻止整个表的原因是什么,我的意思是什么样的 phenomena
在这种情况下阻止整个表被阻止?
最佳答案
默认情况下,InnoDB 在 Repeatable Read
中使用一致的快照隔离级别,这意味着您可以获得元组和范围的可重复读取。
即使 SQL 标准说 Phantom Reads
被 Serializable
阻止,而 Repeatable Read
可能不会阻止它。
有关间隙锁定如何工作的更多详细信息,请查看 this post written by Percona .
关于mysql - MySQL 尝试通过在非索引列上执行 Delete 语句时锁定整个表来防止什么现象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53452571/