使用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
血栓素2:
START TRANSACTION;
INSERT INTO test(quantity) VALUES (40);
COMMIT;
对于tx2,我得到以下结果:
Lock wait timeout exceeded; try restarting transaction
我明白,因为 quantity
列未编入索引,则 delete
语句执行全表扫描,锁定所有行(与 where
条件匹配与否),并在聚集索引中的最后一个索引记录之前和之后应用间隙锁,从而生成完全阻塞的表 insert
来自tx2的语句无法为要插入的行获取锁。
从mysql手册(对于可重复读取隔离级别):
对于具有唯一搜索条件的唯一索引,innodb只锁定找到的索引记录,而不锁定它前面的间隙。
对于其他搜索条件,innodb会锁定扫描的索引范围,使用gap locks或next key locks来阻止其他会话插入该范围所覆盖的间隙(在我的例子中使用)。
考虑到任何给定隔离级别的锁定都是为了防止 phenomenas
我有点搞不清楚,在这种情况下,为什么要把整张table堵起来,我是说什么样的原因 phenomena
在这种情况下,用阻塞整个table来防止吗?
1条答案
按热度按时间flmtquvp1#
默认情况下,innodb在可重复读取隔离级别中使用一致的快照,这意味着您可以获得元组和范围的可重复读取。
即使sql标准说通过serializable阻止虚读,而repeatable read可能不会阻止虚读,但如果较低的隔离级别提供比标准所设想的更好的保证,也不是问题。
有关间隙锁定工作原理的更多详细信息,请参阅本文。