InnoDB隔离级别下存在的问题以及解决办法

概要

注:本文着重讲解各种隔离权限下出现的问题以及解决方法,并不会仔细讲解MVCC机制以及隔离权限的一些基本问题,需要读者有一定基础。

问题

一、RC级别是怎么解决RU级别下的脏读问题的?

  • 答案:使用MVCC机制解决。
  • 假设现在存在A、B事务。
  • 在RU级别下,如果A事务修改了某条记录1且没有提交,那么B事务可以直接读到该记录1的最新状态。(注意,A事务修改某条记录这个动作是在Buffer Pool中完成的,B事务读取的是Buffer Pool中记录的最新状态
  • 在RC级别下,B事务每次执行select,都会生成一张快照,快照中包含当前除了自身事务id以外,当前整个innodb系统中的其他活跃事务Id。如果A修改了某条记录1且没有提交,那么A事务的事务ID必定包含在B事务 的快照中,这意味着B无法读取该版本的记录1,所以B事务会根据记录1的「历史版本指针列」,从UndoLog中找到记录1的上一个版本继续重复此动作,直到记录1的「最后修改此记录的事务ID列」的事务ID不在B此次select产生的快照中为止,当前的版本就是B可以读取的版本。
  • 注意,UndoLog是一个文件,它会在事务开启前记录记录的旧值,一方面可以用于事务回滚,另一方面就是用于MVCC的多版本并发控制。
  • 这里讲个题外话...如果事务A修改了记录1,应该是拿到了记录1的写锁了,那么事务B是如何读到这个数据的呢?其实事务B执行的是普通的select语句,普通的select语句是不会要求加读锁的,只有执行select for update语句才会加读锁。这点希望读者记住别把自己搞混了(其实我自己搞混过hhh)

二、RR级别是怎么解决RC级别下的不可重复读问题的?

  • 答案:使用MVCC机制解决。
  • 假设现在存在A、B事务。
  • 在RC级别下,每次select都会产生一张新快照。假设现在有以下时间轴及其事件:
  • 事务A执行了一次select,查出了记录1当前的值—>随后事务B对该条记录进行了修改并且提交—>事务A再次执行相同的select查询记录1。
  • 由于是RC级别,第二次select时会生成一张新快照,而此时事务B已经提交了,意味着此时事务A读取记录1的「最后修改此记录的事务ID列」获取的事务B的事务ID,绝对会小于这张快照中的最小事务ID,也就是说事务A可以读取当前版本的记录1。
  • 于是乎便出现了事务A在两次执行select,同一条记录的值却不同的现象。
  • 在RR级别下,只有第一次select会生成快照,后续所有的select都会复用这张快照,那么在上述的例子中,虽然第二次select时,事务B已经提交了,但是事务B的ID绝对大于这个快照中的最大事务ID或者存在于快照中(事务B要么在事务A的第一次select之前就已经开启了,要么在事务A的第一次select之后开启。如果是前者,那么事务A第二次select时,事务B的ID肯定在快照中,如果是后者,那么事务B的ID虽然不在快照中,但是一定大于快照中的最大事务ID),也就是说,该记录的当前版本无法被A读取,也就不会出现不可重复读的问题了。

三、InnoDB的RR级别如果使用快照读,是如何使解决幻读问题的?

  • 答案:快照读下使用MVCC解决
  • 假设现在存在A、B事务。
  • 假设现在有以下时间轴及其事件:
  • 事务A执行了一次select全表,查出了0条记录—>随后事务B对该表插入一条数据—>事务A再次查询全表。
  • 由于RR级别的第二次select会复用第一次select的快照,所以这条新纪录对应的事务B的ID绝对大于这个快照中的最大事务ID或者存在于快照中(理由跟上个问题中的一样,其实二、三两个问题的本质是差不多的),也就是这条记录的当前版本无法被事务A读取,那么事务A就会去追溯这个记录的上一个版本。
  • 很明显,这个记录的「历史版本指针列」指向的是null,因为当前版本是这个记录的唯一版本,也就是说这条记录对于事务A来说是不可见的,事务A也就读不到这条记录了。(思考一下,如果是RC级别,在这个例子中会怎么样呢?

四、InnoDB的RR级别如果使用当前读,是如何使解决幻读问题的?

  • 答案:快照读下使用LBCC解决
  • 详情这边不作赘述了,网上有特别多关于间隙锁的原理。

小结

  • 学了就忘是很正常的事情,为了方便记忆,对于以上问题我列举一下着重点。
  • 问题1: 关键点在于RC级别下,未提交的事务ID,必定在另一个事务select时的快照中。
  • 问题2和3本质是一样的,关键点在于RC和RR下生成快照的时机不同,记忆时都可以用「事务A两次select中事务B update or insert 并提交,两种级别各自会发生什么事?」 这个模板去记忆就可以记得很牢固了。
  • MVCC解决幻读的本质还是让读事务读老数据,而LBCC解决幻读的本质是不让写事务写数据,两者的侧重点不同。
  • 24
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值