MySQL中RR级别下的MVCC

众所周知MySQL中InnoDB的可重复读是通过MVCC实现的。

MVCC是由哪些元素构成?

MVCC的读 又叫快照读,在MySQL中不可能把整个表的数据拷贝一份来提供这个快照。它通过

      1、undolog

           InnoDB增删数据时除了redo log外还会记录undo log。

           以update举例: undolog->修改内存中数据页->redolog prepare->binlog-> commit; 修改数据时 undo log记录原始数据。用于以后或许会发生的回滚操作。

      2、表中的的隐藏列 data_trx_id,data_roll_pt

            一张表中有三个隐藏列

            rows_id: MySQL给予行的一个标识。如果表中没有主键,那么就会使用row_id来组织数据。

            data_trx_id: 事务id,创建一个新的事务,会分配一个自增的全局唯一的data_trx_id。

            需要说明的是:begin/start transaction 命令并不是一个事务的起点,在执行到它们之后的第一个操作 InnoDB 表的语句,事务才真正启动。

            data_roll_pt: 回滚指针,这个指针指向undo log中的一行记录原始记录。

      3、Read View数组

            创建事务时,InnoDB为事务创建了一个Read View的数组用来记录创建事务时刻的当前活跃事务data_trx_id。

            

            低水位:创建当前事务时刻活跃事务中最小的data_trx_id。很多人认为是已提交事务的最大data_trx_id,这样理解之后存在一个问题。

            比如 现在已提交事务有 1 3 ,2为活跃事务。按已提交事务的最大id来理解,低水位应该为3。与MySQL判断 小于低水位为已提交事务,就出现了矛盾。 

            高水位:创建当前事务时刻未分配的最小data_trx_id。

以上三部分来实现。

MVCC怎么工作的?

             当读取到一行数据

                     0、是否是当前事务修改,是当前事务修改,当前事务可见。

                     1、这行数据data_trx_id与低水位比较,小于低水位,则事务已提交,当前事务可见。否则判断是否大于高水位。

                     2、这行数据data_trx_id与高水位比较,大于高水位,则是在当前事务创建之后的事务,当前事务不可见。

                     3、这行数据data_trx_id与高水位比较,小于高水位,则判断Read View中是否包含此data_trx_id。如果包含则表示

当前事务创建时,data_trx_id为活跃事务,当前事务不可见。

                      4、Read View中不含此data_trx_id则表示当前事务创建时,data_trx_id为已提交事务,当前事务可见。

             举个栗子:现在已提交事务有 1 3 ,2为活跃事务,当前事务data_trx_id为4。低水位为2,高水位5。

             此时Read View中为 2 4。当读到data_trx_id为3的行时,

             1、3<2?

             2、3>5?

             3、Read View包含3?

             最后得出3对4可见。

跟undolog有什么关系?

      沿用上面的例子, 新起一个事务update对原来为data_trx_id为3的已提交事务进行操作。记录undolog,将data_trx_id由3改为5,并且data_roll_pt指向undolog中为data_trx_id为3的记录。

      当data_trx_id为4的事务,读取到data_trx_id为5的行时,data_trx_id不满足条件则通过data_roll_pt查找undolog中是否有满足条件的行,可以查找到data_trx_id为3的行。

发布了16 篇原创文章 · 获赞 4 · 访问量 1943

猜你喜欢

转载自blog.csdn.net/qq_36592473/article/details/105313172