InnoDB如何在RR隔离级别下实现避免幻读的?

我是方圆,让我们一起来提高

1. InnoDB如何在RR隔离级别下实现避免幻读的?

InnoDB引擎,RR隔离级别下,并不能完全组织幻读的发生,想避免幻读,要保证gap锁是开启的,也就是innodb_locks_unsafe_for_binlog参数值为off(默认情况是off)

  1. 表象:快照读通过MMVC(基于事务版本控制的协议)和undo日志实现的。

在这里要区分一下快照读和当前读
快照读:就是普通的select
select * from table
当前读:加了锁的增删改查,读取的都是当前最新的数据
select * from table where ? lock in share mode;
select * from table where ? for update;
insert;
update ;
delete;

对于快照读的场景,通过mvcc版本管理来解决幻读的问题。就是a事务只做了两次查询操作,两次查询中间即使有符合条件的插入,第二次查询的结果也是原来的数据信息。但是这仅仅是表象,我们继续看内因。

  1. 内因:Next-Key(行锁和gap锁)
    针对当前读的情况,mysql是通过Next-Key锁搞定的。就是在当前读的情况下,会加入一个范围锁,锁住一个区间,区间内如果有别的事务进行插入操作,是要等待当前事务提交的。
  • 在where条件全部命中的情况下,不加gap锁
    由于操作就在这个精确的范围内,再新加入数据也不会影响这些数据,那么不会发生幻读,也不触发gap锁
#在table表中精确查询id为1 3 5 的数据,假如全部都能查到,不加gap锁
select * from table where id in (1,3,5)
  • 在where条件没全部命中的情况下,触发gap锁
#在table表中精确查询id为1 3 5 的数据,只能部分查到1
#那么3 5会加gap锁,插入id为3和id为5的值时,要等事务1的查询结束提交才能插入
select * from table where id in (1,3,5)
  • gap锁的范围
    若 id的值为2,6,9,11,15,那么范围为(-∞,2],(2,6],(6,9],(9,11],(11,15],(15,+∞)
原创文章 56 获赞 19 访问量 6019

猜你喜欢

转载自blog.csdn.net/qq_46225886/article/details/105993728