MySQL:INSERT被外键引用行的UPDATE阻塞

时间:2018-04-16 08:38:19

标签: mysql foreign-keys innodb rowlocking

让我用SQL示例开始我的问题......

这是表格设置,

  1. 创建表X和Y.使用y.x指x.id。
  2. 在X(id = 1)
  3. 中插入一行
    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,Precona 5.7.21,Mariadb 10.2.14上进行了测试

1 个答案:

答案 0 :(得分:0)

是的,这是预期的。

Trx A在记录上有一个独占锁(X),因为它正在更新它。

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

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

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