1.什么是幻读?
时刻 | 事务A | 事务B |
T1 | begin; select * from t where id = 1; | |
T2 | begin; insert into t values(1,1); commit; | |
T3 | update set d = 5 where id=1; | |
T4 | select * from t where id=1; |
事务A在T1时刻查询id=1的记录是查询不到数据的,然后事务B在T2时刻插入了一条id=1的数据,然后事务A在T3时刻更新id=1的记录成功了,最后事务A在T4时刻查询id=1的记录能够查询到,这个案例就是幻读的一种;
因为按照可重复读的隔离级别规则:同一条查询语句在事务中执行的不同时刻结果应该是一样的,但是在T1、T4时刻执行同一条查询语句得到的结果不一样,就让人感觉产生了幻觉,这就是幻读。
2.那如何解决幻读呢?
(1)把隔离级别设置为串行化,但是这样的话效率就比较低了,只能先执行完A事务才能执行B事务;
(2)在可重复读的隔离级别下,mysql的innodb引擎引入了间隙锁,在一定程度了解决了幻读问题。
使用如下形式查询可以解决幻读:
时刻 | 事务A | 事务B |
T1 | begin; select * from t where id = 1 for update; | |
T2 | begin; insert into t values(1,1); commit; | |
T3 | update set d = 5 where id=1; | |
T4 | select * from t where id=1 for update; |