MySQL的不可重复读和幻读

不可重复读

     不可重复读是指在同一个事务中,两次(或以上)查询发现符合条件的数据记录的字段值发生了变化,导致不可重复读出现的原因主要是update操作

不可重复读的例子

  1. Alice和Bob开启了数据库的两个事务;
  2. Bob读取post_comment表中所有post_id为1的数据;
  3. Alice修改了post_id为1的数据;
  4. Alice提交了她的事务;
  5. 如果Bob重复读取post_id为1的数据,他将发现结果集的字段值发生了变化;

幻读

     幻读是指在同一个事务中,两次(或以上)查询同一个范围内的数据,发现数据的数量不同,导致幻读问题的原因主要是insert和delete操作

幻读的例子

  1. Alice和Bob开启了数据库的两个事务;
  2. Bob读取post_comment表中所有post_id为1的数据;
  3. Alice增加了一条post_id为1的数据;
  4. Alice提交了她的事务;
  5. 如果Bob重复读取post_id为1的数据,他将发现结果集的记录数量发生了变化;

幻读的重点在于新增或者删除
不可重复读的重点是修改

 

在MySQL中不可重复读和幻读的解决办法(在RR隔离界别中)

     MVCC(多版本并发控制)保证了数据的可重复读,也保证不会读到幻读数据(即使是有新的符合条件的数据产生,在同一个事务的下次查询中也查不到,蒙蔽自己的双眼假装看不到)

     在MySQL的InnoDB存储引擎中,MVCC普通方式(select * from table)查询数据是不加任何锁的,数据的筛选除了通过查询条件之外,还要根据数据行的隐藏字段(两个版本号)来和事务的版本号来进行比较后过滤. 这样做的好处是支持的并发量更高(因为不加锁),根据版本号来过滤数据也解决了不可重复读的问题,也能保证不会读到幻读数据

     record lock(记录锁)和gap lock(间隙锁)保证了幻读数据不会产生(在读取数据的时候加锁,防止在读取时有其他事务对读取条件内的数据做增删改操作)

     也就是说如果你要完全解决幻读问题,还要在查询语句中使用像lock in share mode和for update这样显式的加锁语句

ps: 本人新手一个,如果有什么写的不对的,希望各位大佬能帮忙指正一下,感谢

你可能感兴趣的:(MySQL)