1.版本链对于InnoDB存储引擎来说,其聚簇索引记录中包含两个隐藏列:
- trx_id:一个事务每次对聚簇索引记录做出改动的时候,都会把该事务的事务id复制给此列
- roll_point:每次对某条聚簇索引记录进行改动的时,都会把旧的版本写入到undo 日志中,此列相当于一个指针,指向修改前的信息

文章插图
每次修改都会形成Undo 日志,所有版本的数据会通过roll_point串联成一个链表,称之为版本链,头节点是当前记录的最新值 。利用版本链控制多个并发事务访问相同记录时的行为称为MVCC多版本并发控制 。
其实在undo日志中,只记录被更新列的信息,而不是记录全部的信息,对于没有记录的列,会通过版本链找少一个版本中的对应列的信息,直到找到聚簇索引叶子节点中的内容2.Read View对于使用Read Uncommitted隔离级别的事务,可以读取到没提交的数据,那么直接读取最新的版本即可 。对于Serializable隔离级别,innodb直接通过加锁来访问记录 。对于read committed 和 repeatable read隔离级别的事务,都必须保证督导的数据是已经提交事务修改过的记录,那么如何判断版本链中的哪个版本的数据是当前事务可见的昵?
innodb 使用的Read View
2.1 read view 的结构

文章插图
- m_ids:在生成read view时,当前系统中活跃的读写事务id列表
- min_trx_id:生成read view时,当前系统中活跃的读写事务中最西澳的事务id,也就是m_ids中的最小值
- max_trx_id:生成read view时,系统应该分配给下一个事务的事务id值
- creator_trx_id:生成该read view的事务的事务id
- 如果被访问版本的trx_id和creator_trx_id相同,意味着当前事务在访问自己修改的记录,自然可见
- 如果访问版本的trx_id属性值小于read view中的min_trx_id 表明此版本是生成read view之前已经提交的事务,那么自然可见
- 如果访问版本的trx_id,大于等于read view中的max_trx_id说明,当前版本数据是生成read view后开启事务产生的,那么自然不可见
- 如果访问版本的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
经验总结扩展阅读
- C#多线程之线程基础篇
- 豆腐在冷藏室可以放几天
- 200ml牛奶是多少克
- 一碗米饭的热量是多少
- 45岁男士体脂率多少正常 45岁男人体脂率多少
- 70多岁还能骑自行车吗 70岁老人能骑自行车吗
- 虾干热量有多少 虾干的热量是多少
- 一个水煮蛋多少大卡
- 板栗放冰箱里能存放多久
- 螃蟹干放着能活多久