什么是ReadView,什么样的ReadView可见 ?
一、定义
ReadView 是 InnoDB 中一个至关重要的概念,它是实现MVCC的基础,同时他也是支持不同的事务隔离级别的基础,同时提高系统的并发能力和性能。
它到底是干啥的?简单来说,其实就是一句话:读视图(Read View) 主要来帮我们解决可见性的问题的, 即它会来告诉我们本次事务能看到哪个 undolog版本,不能看到哪个undolog版本
我们都知道,MySQL中用不同的事务隔离级别,比如我们常见的 RR 和 RC,RR要求在一个事务中,多次读取的结果是保持一致的,而RC则要求每次都要读取到最新的值。
那么,具体如何实现的RR和RC的读数据的时候的不同现象,就是这个快照
在可重复读(Repeatable Read)级别下,读视图(ReadView)会在事务中第一次 select 语句执行时生成,在本事务中第二次 select 语句时会复用第一次的读视图(ReadView),只有在本事务中对数据进行更改才会更新读视图
在读已提交(Read Committed)级别下,每次读取都会重新生成一个读视图(ReadView),总是读取行的最新版本
在mysql5.6中的 ReadView 的定义更加直观:

也就是说,在 Read View 中有几个重要的属性:
- 
trx_ids,表示在生成 ReadView 时当前系统中活跃的读写事务的 事务id 列表 
- 
low_limit_id,应该分配给下一个 事务的id 值 
- 
up_limit_id,未提交的事务中最小的事务 id 
- 
creator_trx_id,创建这个 Read View 的事务id 
 trx_ids 中包含了 low_limit_id 和 up_limit_id 的信息,其实 trx_ids = [up_limit_id,low_limit_id)
(但是需要注意,它并不一定连续,只是会包含 up_limit_id,并且小于 low_limit_id,比如他可能是5, 7, 8, 11),
并且你没看错,up_limit_id 就是表示最低水位,low_limit_id 就是表示最高水位
网上还有些资料这里有 min_trx_id、max_trx_id、m_ids等的说法,我翻了下源码5.6、5.7、8.0,并没有找到出处。就先不纠结了,以源码为准。
也就是说,每一次读取数据的时候(RC情况下),都会生成一个 ReadView,并且在其中记录上 trx_ids(包含了[up_limit_id, low_limit_id))和 creator_trx_id
那么,一个事务能看到哪个 undolog版本,不能看到哪个undolog版本该如何判断呢 ?
假如一个 ReadView 的内容为:
trx_ids = [5,6,8)
low_limit_id = 8
up_limit_id = 5
creator_trx_id = 7
假设当前事务要读取某一个undolog版本的记录行,该记录行的事务id为:db_trx_id,那么,就有以下几种情况了:
- 
1、db_trx_id < up_limit_id,即小于5的事务,说明该事务 db_trx_id 在生成ReadView之前就已经提交了,那么该事务的结果就是可见的 
- 
2、db_trx_id > low_limit_id,即大于8的事务,说明该事务db_trx_id 在生成 ReadView 后才生成,所以该事务的结果就是不可见的 
- 
3、up_limit_id < db_trx_id < low_limit_id,即大于等于5,小于8,这种情况下,会再拿事务id 和 Read View 中的 trx_ids 进行逐一比较 - 
如果,事务id 在 trx_ids 列表中,如6,那么表示在当前事务开启时,这个事务还是活跃的,那么这个记录对于当前事务来说应该是不可见的 
- 
如果,事务id 不在 trx_ids 列表中,如7,那么表示的是在当前事务开启之前,其他事务对数据进行修改并提交了,所以,这条记录对当前事务就应该是可见的 
- 
当然这里有个例外情况,那就是这个 db_trx_id = creator_trx_id,说明当前undolog版本的记录行是由创建这个 Read View 的事务提交的,那么就肯定是可见的 
 
- 
总结一下就是,一个事务,能看到的是在它开始之前就已经提交的事务的结果,而未提交的结果都是不可见的。 
 
                    
                
 
                
            
         浙公网安备 33010602011771号
浙公网安备 33010602011771号