定义:事务A 按照一定条件进行数据读取, 期间事务B 插入了相同搜索条件的新数据,事务A再次按照原先条件进行读取时,发现了事务B新插入的数据称为幻读。(读到了其他事务新插入的数据)
创建表和数据(Mysql 隔离级别为 可重复读)
DROP TABLE IF EXISTS `user`;
CREATE TABLE `user` (
`id` bigint(10) NOT NULL,
`username` varchar(50) DEFAULT NULL,
`age` int(10) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-- ----------------------------
-- Records of user
-- ----------------------------
INSERT INTO `user` VALUES ('1', 'zhuangsan', '17');
INSERT INTO `user` VALUES ('2', 'lisi', '18');
INSERT INTO `user` VALUES ('3', 'wangwu', '18');
进行以下的操作:
A事务
BEGIN
-- T1时刻A事务查询所有年龄为18的用户
SELECT * FROM `user` where age = 18
-- T3时刻A事务查询所有年龄为18的用户
SELECT * FROM `user` where age = 18
-- T4时刻更新所有年龄为18的用户
UPDATE `user` SET username = 'ss' WHERE age = 18
-- T5时刻A事务查询所有年龄为18的用户
SELECT * FROM `user` where age = 18
B事务
-- T2时刻,B事务插入一条数据
INSERT INTO `user` VALUES (4,'sherlock',18)
在T1~T3时刻,可重复读隔离级别下貌似没有幻读问题,但实则不然。在T4时刻的影响条数是3条,T5时刻查出来的数据也是三条,产生了幻读的问题。
那么在可重复读级别下,能否解决幻读的问题呢?
答案是可以的。可重复读隔离级别下,一个事务中只使用当前读,或者只使用快照读都能避免幻读。
在快照读读情况下,Mysql通过MVCC来避免幻读。
在当前读读情况下,Mysql通过next-key来避免幻读。
什么是快照读和当前读
- 快照读:简单的select操作,属于快照读,不加锁。
- select * from table where ?;
- 当前读:特殊的读操作,插入/更新/删除操作,属于当前读,需要加锁。
- select * from table where ? lock in share mode;
- select * from table where ? for update;
- insert into table values (…);
- update table set ? where ?;
- delete from table where ?;
网友评论