MVCC
事务的隔离级别分为四种,其中Read Committed和Repeatable Read隔离级别,部分实现就是通过MVCC(Multi-Version Concurrency Control,多版本并发控制)
版本链
-
版本链是通过undo日志实现的,
-
事务每次修改一次记录,都会生成一条undo日志,将记录被修改字段之前的值、trx_id、roll_pointer写到undo日志中,
-
修改记录的同时将当前事务的id赋值给记录的trx_id,记录的roll_pointer指向刚生成的undo日志,这样子就构成了由roll_pointer字段串起来的链表,叫做版本链。
-
-
当然插入类型的undo日志没有roll_pointer,是版本链的尾节点,当然它对于MVCC机制也没有作用。
ReadView
ReadView(一致性视图)是实现Read Committed和Repeatable Read隔离级别的一个重要结构。上述两种隔离级别,要求事务不能读到另一个活跃事务没有没有提交的修改的记录。当检索到该条记录,就会通过ReadView中的属性对比记录和undo日志上的trx_id进行筛选,不符合条件则按照版本链不断向后遍历。
-
ReadView中包含以下属性:
-
m_ids:创建ReadView时,当前系统中活跃的读写事务的id列表。
-
min_trx_id:创建ReadView时,当前系统中活跃的读写事务的最小id,也就是m_ids的最小值。
-
max_trx_id:创建ReadView时,系统应该分配给下一个事务的id。不是m_ids的最大值。
-
creator_trx_id:创建ReadView的事务的id
-
-
过滤可视记录
-
针对聚簇索引记录:访问记录的筛选过程,如果符合条件,则会返回结果,否则沿着版本链向后遍历,当前访问呢记录的trx_id如果
-
小于min_trx_id,则说明修改该记录的事务已经提交,符合要求。
-
大于等于max_trx_id,则说明修改该记录的事务在创建ReadView时还未出生,不符合要求。
-
被包含在m_ids,则说明修改该记录的事务在创建ReadView时还未提交,不符合要求
-
等于creator_id,则说明这条记录就是自己改的,符合要求。
-
其他情况都符合要求。
-
-
二级索引记录:首先会根据记录所在页的的Page Header的PAGE_MAX_TRX_ID属性(表示修改该页的最大的事务id)进行粗略判断
-
如果该值小于min_trx_id,则该页的所有记录都符合要求,可以被当前事务看见
-
否则就会回表,通过聚簇索引记录来判断。
-
-
-
隔离级别运用
-
Read Committed:每次读取数据前创建一个ReadView,可能会导致,同一个事务读取同一条记录两次,结果都不一样(期间有事务修改记录并提交了)
-
Repeatable Read:每个事务第一次读取记录前创建一个ReadView,该事务内读取所有数据都一致。
-
purge阶段
-
每个事务生成的undo日志被划为一组,并且事务提交时,还会生成一个事务no分配给这组undo日志(事务no全局变量,每次分配后自增1)
-
生成ReadView时会获取当前系统的事务no并且加一存储起来(这个不算分配)
-
-
如果undo日志组的事务no小于当前系统事务no最小的ReadView的事务no,则说明这组事务永远不会被访问到,就可以被回收了,如果这组undo日志中有逻辑删除记录的情况,则将这条记录彻底删除。