MySQL 试图通过在对非索引列执行 Delete 语句时锁定整个 table 来阻止什么现象
What Phenomena does MySQL try to prevent by locking the whole table upon executing Delete statement with the condition on a non-indexed column
使用 Repea 的 MySQL 隔离级别table 读取。
给定 table test
具有非索引列 quantity
:
id | quantity
--------------------
1 | 10
2 | 20
3 | 30
Tx1执行1st,注意还没有commit,意思是所有获取的锁还没有释放
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
语句进行完整的 table 扫描,锁定所有行(与 where
条件是否匹配)并且还在聚集索引中的最后一个索引记录之前和之后应用间隙锁,导致完全阻塞 table 因此来自 tx2 的 insert
语句无法获取锁要插入的一行。
来自MySQL manual(对于Repeatable读取隔离级别):
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
我有点困惑在这种情况下阻止整个 table 的原因是什么,我的意思是在这种情况下阻止整个 table 会阻止什么样的 phenomena
?
默认情况下,InnoDB 在 Repeatable Read
隔离级别使用一致的快照,这意味着您可以获得元组和范围的可重复读取。
即使 SQL 标准说 Phantom Reads
被 Serializable
阻止并且 Repeatable Read
可能不会阻止它。
有关间隙锁定工作原理的更多详细信息,请查看 this post written by Percona。
使用 Repea 的 MySQL 隔离级别table 读取。
给定 table test
具有非索引列 quantity
:
id | quantity
--------------------
1 | 10
2 | 20
3 | 30
Tx1执行1st,注意还没有commit,意思是所有获取的锁还没有释放
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
语句进行完整的 table 扫描,锁定所有行(与 where
条件是否匹配)并且还在聚集索引中的最后一个索引记录之前和之后应用间隙锁,导致完全阻塞 table 因此来自 tx2 的 insert
语句无法获取锁要插入的一行。
来自MySQL manual(对于Repeatable读取隔离级别):
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
我有点困惑在这种情况下阻止整个 table 的原因是什么,我的意思是在这种情况下阻止整个 table 会阻止什么样的 phenomena
?
默认情况下,InnoDB 在 Repeatable Read
隔离级别使用一致的快照,这意味着您可以获得元组和范围的可重复读取。
即使 SQL 标准说 Phantom Reads
被 Serializable
阻止并且 Repeatable Read
可能不会阻止它。
有关间隙锁定工作原理的更多详细信息,请查看 this post written by Percona。