【问题标题】:Inner working of MySQL multivalue insert for InnoDB engineInnoDB 引擎的 MySQL 多值插入的内部工作
【发布时间】: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 是主键,那么如果它执行行级锁定,那么在多线程环境中它是如何工作的?

标签: mysql innodb


【解决方案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

【讨论】:

    猜你喜欢
    • 2013-07-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-01-26
    • 2012-10-02
    • 1970-01-01
    相关资源
    最近更新 更多