mysql试图通过在执行delete语句时用非索引列的条件锁定整个表来防止什么现象

y0u0uwnf  于 2021-06-17  发布在  Mysql
关注(0)|答案(1)|浏览(310)

使用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来防止吗?

flmtquvp

flmtquvp1#

默认情况下,innodb在可重复读取隔离级别中使用一致的快照,这意味着您可以获得元组和范围的可重复读取。
即使sql标准说通过serializable阻止虚读,而repeatable read可能不会阻止虚读,但如果较低的隔离级别提供比标准所设想的更好的保证,也不是问题。
有关间隙锁定工作原理的更多详细信息,请参阅本文。

相关问题