【问题标题】:MySQL: INSERT blocked by an UPDATE of the foreign key referenced rowMySQL:INSERT 被外键引用行的 UPDATE 阻塞
【发布时间】:2018-04-16 08:38:18
【问题描述】:

让我从一个 SQL 示例开始我的问题。

这是表格设置:

  1. 创建表xyy.x 指的是x.id
  2. x (id=1) 中插入一行。

START TRANSACTION;
CREATE TABLE `x` (
    `id` INT(11) NOT NULL AUTO_INCREMENT,
    `value` INT(11) NOT NULL,
    PRIMARY KEY (`id`)
)  ENGINE=INNODB;
CREATE TABLE `y` (
    `id` INT(11) NOT NULL AUTO_INCREMENT,
    `x_id` INT(11) NOT NULL,
    `value` INT(11) NOT NULL,
    PRIMARY KEY (`id`),
    CONSTRAINT `fk_x` FOREIGN KEY (`x_id`)
        REFERENCES `x` (`id`)
)  ENGINE=INNODB;

INSERT INTO x values (1,123456);
COMMIT;

现在开始一个事务 (Trx A) 以更新 x 中的行。

START TRANSACTION;
UPDATE x SET value=value+1 WHERE id = 1;

在提交之前,我正在启动另一个事务 (Trx B) 以向y 插入一行。

START TRANSACTION;
INSERT INTO y VALUES (null,1,123456);
---- HANGED ----
-- Until Trx A is committed or rolled-back, the Trx B is hanged here.

问题是 - 预计 Trx B 会在那时被绞死吗?为什么以及任何解决方法?

这已经在 MySQL 5.7.21、Percona 5.7.21、MariaDB 10.2.14 上进行了测试

【问题讨论】:

    标签: mysql foreign-keys innodb rowlocking


    【解决方案1】:

    是的,这是预期的。

    Trx A 在记录上具有排他锁 (X),因为它正在更新它。

    Trx B 必须在所有外键引用上获取共享模式 (S) 锁,以确保满足约束条件。它等待 Trx A 释放它的 X 锁。

    没有办法避免这种情况并保持参照完整性。如果您设法禁用锁定,MySQL 将无法保证引用的行存在。

    通常的解决方法是删除外键。

    【讨论】:

    • 叹息-很遗憾,但谢谢。我认为不更新密钥不会导致这种情况发生。
    • “不更新密钥”是什么意思
    • 我的意思是我希望有一种方法可以向 MySQL 保证在插入 x.id 后我不会修改它(仅更新其他“值”列),因此不会破坏参照完整性.我想根本就没有这种东西。
    • 有:) 您可以禁用外键检查或删除外键。
    • FK 是INSERTs 的负担——检查事情;正如这所指出的,FK 是交易的负担。如果性能是个大问题,请考虑调试您的应用,然后删除 FK。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-12-15
    • 2013-11-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-11-18
    相关资源
    最近更新 更多