MySQL 5.7,事务隔离级别为 repeatable read
。
我有两个表,class
和 student
。它们看起来像:
class_id int not null primary key auto increment
class_name varchar
remark varchar
student_id int not null primary key auto increment
class_id int not null
student_name varchar
....
我也有一个外键 class_id_fk
(外键名称和字段为 class_id
)在 student
引用 class_id
的 class
, {{1} } 是 on delete
,restrict
是 on update
。
我尝试启动两个事务,例如:
restrict
trx1 trx2
set autocommit=0;
update class set remark='test' where class_id=1; set autocommit=0;
insert into student(class_id, student_name) values(1, 'n1');
commit;
commit;
中的 class_id=1
和 trx1
也在 trx2
中插入带有 class_id=1
的数据。
在 trx2
中运行 insert into student(class_id, student_name) values(1, 'n1');
时,MySQL 抛出 trx2
。
我试过,发现在某些情况下不会出现这个错误:
Lock wait timeout exceeded; try restarting transaction
和 update class with class_id=1
在同一个事务中insert student with class_id=1
中的update class with class_id=1
和trx1
中的update student with class_id=1
(顺序同上)trx2
中的 update class with class_id=1
和 trx1
中的 insert student with class_id not equal 1
那么为什么我的案例会抛出这个错误?
如果我删除 trx2
中的外键 class_id_fk
,那么这个错误就会消失。
是不是说如果student
中有外键{{1}},那么class_id_fk
中有student
,MySQL会在这条记录中添加update class with class_id=1
,当trx1
未提交,而在 exclude lock
中执行 trx1
需要检查 insert into student with class_id=1
是否有 class_id=1 的记录(但是如果它是 trx2
不需要检查?),但是这条记录已经被class
锁定,所以update student with class_id=1
必须等待trx1
提交,这样它才能检查trx2
是否存在于{ {1}} 与否,对吗?