测试使用的隔离级别为Read Repeatable
建表和插入数据的SQL语句
create table test1(id int auto_increment primary key, no int, key(no));
create table test2(id int auto_increment primary key, no int, key(no));
insert into test1(no) values (1), (1), (1);
insert into test2(no) values (2), (2), (2);
情况一,直接上代码
事务1中执行的SQL语句(略去start transaction和commit,下同),先执行
update test1 set no = 4 where id = 1;事务2
update test2 a set no = (select no from test1 where id = a.id) where exists (select no from test1 where id = a.id) and id = 2;两个事务都正常执行。
情况二
事务1,先执行
update test1 set no = 4 where id = 2;事务2
update test2 a set no = 5 where exists (select no from test1 where id = a.id) and id = 2;事务2先阻塞,等事务1 commit之后,事务2才执行该SQL语句,正常执行。
情况三
事务1,先执行
update test1 set no = 4 where id = 2;事务2
update test2 a set no = (select no from test1 where id = a.id) where exists (select no from test1 where id = a.id) and id = 2;事务2先阻塞,等事务1 commit之后,事务2才执行该SQL语句,但是表test2中id为2的行no为4,在事务2中看到了事务1中修改的值,和select * from test1 where id = 2 for update的结果相同。
情况四
和情况三语句相同,但过了锁超市时间,就报ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction
Mysql应该是通过S/X锁进行处理的。