MVCC

提到快照读和当前读就不得不提到MVCC(多版本并发控制),可以理解为乐观锁的一种具体的实现,Mysql Innodb引擎下,在可重复读和提交读的隔离级别下,会使用到MVCC,每一行数据都会有两个默认字段,及生成版本和删除版本,还有一个指针,指向上一个版本,每开启一个事务,都会有一个版本号,在事务内部执行update或者insert时,会为记录新增一个版本,例如:

一致性视图

一致性视图(Consistent View)是实现MVCC(多版本并发控制)的一个重要概念。它允许事务看到一个一致的数据快照。这意味着,在一个事务内,它不会看到其他并行事务所做的修改,除非这些修改是在一致性视图生成之前之前就已经提交的,但是一致性视图是一个逻辑概念,不同的事务隔离级别生成一致性视图的实际也不一样,如下

  • RR 级别:快照在事务中第一次读操作时生成,后续所有读操作基于此快照。
  • RC 级别:每次读操作生成新快照,保证读到最新提交的数据。

ReadView

上面说到一致性视图是逻辑概念,而ReadView就是实现它的具体手段
read view中存放的是当前活跃事务id,也就是当前还没有提交的事务id,如下图所示,假如在事务之间还存在一个活跃事务id为50,事务A的事务Id为51,事务B为52,事务C为53。那么事务A的read view为[50,51],事务B为[50,51,52],事务C为[50,51,52,53]。

高水位和低水位

  • 高水位指事务创建时当前系统中最大的事务id+1,例如事务A创建时,事务A本身就是最新创建的事务,事务A的高水位就是事务A的事务id加1,即高水位为52
  • 低水位指事务创建时当前系统中最小的活跃事务id,例如事务A创建时,事务A的低水位就是50,也可以理解为read view中最小的事务id
    //注:高水位和低水位是伴随着read view的,所以高水位和低水位是个固定值

高低水位比对规则

mysql在可重复读级别下,读到的数据始终是一致的,原因就是因为高低水位加上一个事务id(这里指的是某个版本的事务id,不是具体事务的事务,为了区分,下面用版本id代替)以及一个比对结果

具体规则:

  • 如果版本id小于等于低水位落在绿色部分,证明这个版本已经提交或者就是当前事务创建的,是可见的
  • 如果版本id大于等于高水位落在红色部分,证明这个版本是当前事务后面的事务创建的,是不可见的
  • 如果版本id大于低水位而小于高水位,则需要分情况
    1. 如果当前事务的read view中不存在该版本id,证明该版本在当前事务创建时已经提交了,是可见的
    2. 如果当前事务的read view中存在该版本id,证明该版本在当前事务创建时还未提交,是不可见的

快照读

根据实际运行,事务B查询的k为3,事务A查询的k为1,事务A的查询就是快照读,如下图,存在52、53、50三个版本,事务A查询到52时,发现大于自己read view的高水位,不可见,继续往下走,53也大于自己的高水位,继续往下走,发现50等于自己的低水位,是可见的,返回这个快照的结果,即查询的k为1,所谓快照读通俗来讲就是访问到以前的快照

当前读

按照MVCC的思想事务B的查询结果应该是2才对,为什么是3呢,这里就涉及到了当前读,当前读只会读取最新的数据,而除了select之外的动作都会触发当前读,所以事务B进行update操作时,最新的版本是53,所以事务B的k值变成了3。
如果事务C没有提交,那事务B的update还会因为当前读访问到事务C的版本吗,这样的话不是违背了提交读吗,这里忘记了一个知识点,update操作会加锁,如果事务C不提交,那么事务B的update会阻塞,也就不存在能不能访问到的问题了,所以当前读的实现是有锁的参与的

可重复读和提交读的区别

可重复读和提交读级别的区别在于read view的机制不一样,可重复读只在创建事务时生成,而提交读会在每次执行查询时重新生成

我们假设事务B比事务A先提交

  • 如果是可重复读级别的话,事务A进行select操作时,由于事务A的read view没有发生变化,事务B在事务A眼里仍然是活跃的,所以事务A还是只会查询到之前的快照
  • 如果是提交读级别的话,事务A进行select操作时,由于事务B和事务C都已提交,事务A会重新生成read view[50, 51],事务A的高低水位也会随着变化,高水位变成54,低水位还是50,而事务B的事务id时52,小于高水位54,且由于已经提交了不在read view中,所以事务B对于记录的更改对于事务A是可见的,这就是读已提交的实现原理

一个小知识
使用navicat时,如果改变了隔离级别,需要将当前查询窗口关掉,重新建查询窗口,不然隔离级别的修改可能不会生效,另外,修改隔离级别时,最好session和global的隔离级别都更改


本站总访问量:次本站总访问数:人
本站由 Peng Tong 使用 Stellar 1.29.1 主题创建。
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处。