InnoDB 引擎的 MySQL 多值插入的内部工作
Posted
技术标签:
【中文标题】InnoDB 引擎的 MySQL 多值插入的内部工作【英文标题】:Inner working of MySQL multivalue insert for InnoDB engine 【发布时间】:2021-08-25 16:27:28 【问题描述】:在插入多值插入时,mysql 是否会执行表级锁定,如下所示?这个语句对于 InnoDB 来说是原子的,所以它会保证全有或全无。 MySQL 在底层是如何处理的?
INSERT INTO MyTable ( Column1, Column2 ) VALUES
( Value1, Value2 ), ( Value1, Value2 )
我已阅读https://dev.mysql.com/doc/refman/8.0/en/innodb-transaction-isolation-levels.html,但找不到与此相关的任何特定内容。
【问题讨论】:
它不会锁定表,只会锁定插入的行和插入的索引。 @SoheilRahsaz 感谢您的回复。所以假设我的 column1 是主键,那么如果它执行行级锁定,那么在多线程环境中它是如何工作的? 【参考方案1】:InnoDB 锁定行而不是表
在这里,我使用带有此示例数据结构的 IntelliJ 控制台创建了一个包含 3 个会话的简单测试用例。
引擎:InnoDB(请注意,我在这里只谈论 InnoDB,我确信不同的引擎是不同的)
Mysql版本:8.0.25
DROP TABLE IF EXISTS `locktest`;
CREATE TABLE locktest
(
id INT UNIQUE KEY,
val INT
);
DROP TABLE IF EXISTS `dataTest`;
CREATE TABLE `dataTest`
(
id INT UNIQUE KEY,
val INT
);
INSERT INTO dataTest
VALUES (1, 1),
(2, 2),
(3, 3),
(4, 4);
现在在会话 1:
START TRANSACTION;
UPDATE dataTest
SET val = 100
WHERE id = 2;
所以现在它正在使用第 2 行并且尚未提交。
然后在第 2 节中:
START TRANSACTION;
INSERT INTO locktest
SELECT id, val from dataTest
WHERE id in (1,2);
正如预期的那样,这不会立即成功,因为它正在等待来自dataTest
的第 2 行的锁定。你可以在这里看到它正在等待:
但它已经成功地将id为1的行插入locktest
。我们怎么知道呢?看Session 3
然后在第 3 节:
START TRANSACTION;
INSERT INTO locktest VALUES (10, 200);
INSERT INTO locktest VALUES (1, 200);
这里显示插入 id 为 10 的行发生得很快,但它必须等待下一次插入到locktest
,因为在会话 2 中我们插入了一个 id 为 1 的行并且该会话尚未完成。
我们得出的结论是 MySQL 没有完全锁定表 locktest
,只锁定 id 为 1 的行(因为 id 是唯一的),它允许插入 id 为 10 的行。
另外,请阅读this 和旁注,注意Gap Locks。
【讨论】:
以上是关于InnoDB 引擎的 MySQL 多值插入的内部工作的主要内容,如果未能解决你的问题,请参考以下文章