Mysql InnoDB多版本并发控制MVCC( 三 )

  • min_trx_id:生成read view时 , 当前系统中活跃的读写事务中最西澳的事务id,也就是m_ids中的最小值
  • max_trx_id:生成read view时,系统应该分配给下一个事务的事务id值
  • creator_trx_id:生成该read view的事务的事务id
  • 2.2 read view 判断某个版本当前事务释放可见的步骤
    1. 如果被访问版本的trx_id和creator_trx_id相同,意味着当前事务在访问自己修改的记录,自然可见
    2. 如果访问版本的trx_id属性值小于read view中的min_trx_id 表明此版本是生成read view之前已经提交的事务,那么自然可见
    3. 如果访问版本的trx_id,大于等于read view中的max_trx_id说明,当前版本数据是生成read view后开启事务产生的,那么自然不可见
    4. 如果访问版本的trx_id 介于min_trx_id和max_trx_id之间 , 需要判断trx_id是否位于m_ids列表中,如果在说明创建read view时生成该版本的事务还是活跃的,那么该版本,不可被访问,如果不在说明创建read view 时生成该版本的事务已经提交,可以被访问到
    如果某个版本数据对当前事务不可见那么需要一直顺着版本链找上一个版本的数据,并通过上述步骤判断是否可见,直到找到可见的版本 , 如果一直找不到说明该条记录对当前事务不可见,查询结果将不包含该记录 。
    2.3 Read Committed和 Repeatable Read的不同
    • Read Committed——每次读取数据前都生成一个Read View
      这样可以保证生成Read view 中的m_ids是实时活跃事务id集合,也许第一次读取的时候事务A没提交 , 其id位于m_ids中,但是第二次读取的时候事务A提交了,事务A将不位于m_ids中 , 这样在第二次读取的时候,通过m_ids判断事务A是否提交的时候 , 可以得到事务A已经提交了,然后让事务A版本产生的数据可见(见2.2.4中的内容) 。
    • Repeatable Read——如果使用begin开启事务那么在第一次查询的时候生成Read view,如果使用start transaction with consistent snapshot 那么执行的时候就会生成read view
      这样可以保证当前事务从头到尾都是read view中记录的内容是一致的,第一次读取的时候事务A没有提交,那么不可见,但是第二次读取的时候事务A提交了,但是read view的m_ids 和max_trx_id可以判断事务A不可见,比如事务A事务id小于max_trx_id意味着生成read view是事务A启动但是没提交,即使第二次读事务A提交了,但是m_ids中还是包含事务A,那么不可见 。如果事务A事务id大于max_trx_id,那么自然第二次还是大于max_trx_id,也是不可见的,从而实现了可重复读 。
    2.4 二级索引与MVCC上面我们提到,innodb聚簇索引组织的记录才具备trx_id和roll_point , 那么我们使用二级索引进行查询的时候,如何判断数据是否可见昵?
    1. 二级索引页面的page header中存在page_max_trx_id属性,每当有事务对其中的记录进行增删改查操作的时候 , 如果事务的事务id , 大于page_max_trx_id,那么会更新page_max_trx_id属性值为其事务id,这意味着page_max_trx_id记录了修改该二级索引页面最大的事务id是多少 。当select通过二级索引首先看下对于read view的min_trx_id是否大于该页面的page_max_trx_id , 如果大于那么页面中所有记录都对该read view可见,否则就进行下面的第二步
    2. 利用二级索引中的主键值,进行回标,得到对应的聚簇索引记录然后进行回表,然后通过2.2中步骤拿到第一个可见版本的数据,然后比对此纪录和通过二级索引查询得到记录的值是否相同,如果相同那么发送给客户端,否则跳过该记录 。

    推荐阅读