让我从一个sql示例开始提问。
以下是表格设置:
创建表 x
以及 y
. 与 y.x
指 x.id
.
在中插入一行 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;
现在启动一个事务(trxa)来更新 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上进行了测试
1条答案
按热度按时间vzgqcmou1#
是的,这是预期的。
trxa在记录上有一个独占锁(x),因为它正在更新它。
trx b必须在所有外键引用上获取共享模式锁,以确保满足约束。它等待trxa释放它的x锁。
无法避免这种情况并保持引用的完整性。如果您设法禁用锁定,mysql将无法保证引用的行存在。
通常的解决方法是删除外键。