事务(四)

MVCC实现

1)Mutli-Version Concurreny Control,多版本并发控制,读不加锁,读写不冲突。应用于 Read Commited 和 Repeatable read 两个事务隔离级别。
快照读: 普通的select,不加锁,读取记录的可见版本。
当前读:select...lock in share mode/for update、update、insert、delete,读取记录最新版本,并加锁。
ibd文件(又叫表空间)中包含数据段,索引段,回滚段(undo log)
回滚段中存储undo log,所谓的多版本数据指的是undo log中的多条记
2)数据行结构

 

 DB_TRX_ID: 这行数据最后插入或修改的事务id

DB_ROLL_PTR:当该行数据被更新的时候,修改前的内容记录到undo log中,回滚指针指向该条undo log记录
DB_ROW_ID:表中不存主键 或者 唯一索引,那么数据库 就会采用DB_ROW_ID生成聚簇索引。
3)undo log
作用:undo log是为回滚而用,具体内容就是copy事务前的数据库内容(行)到undo buffer,在适合的时间把undo buffer中的内容刷新到磁盘。
存储位置:所有的undo log均存放在主ibd数据文件(表空间)中
创建时间:每次对数据进行更新操作时,copy 当前数据,保存到undo log 中,并将当前行的回滚指针指向undo log中的旧记录

 

4)Read View(一致性视图)判断行的可见性
read view (主要用来判断当前版本数据的可见性。):创建一个新事务时,copy一份当前系统中的活跃事务列表。意思是,当前不应该被本事务看到的其他事务id列表。
注意:read view列表(区间范围T_min~T_max)定义:T_min为=当前活跃事务(活跃:已开启但未提交的所有事务)中事务id的最小值,T_max=事务自增id当前值+1(即当前事务id)。
 
Read Commited隔离级别判断算法每次语句执行的过程中,都关闭read_view, 重新创建当前的一份新的read_view。如下:
read view中事务区间 T_min~T_max(T2),当前快照数据隐藏行DB_TRX_ID为:T1,当前事务id为:T2(即区间T_max),判断流程如下:
...执行sql,创建一份最新的read_view;
...T1<T_min,说明T1事务比较早,该行对当前事务T1可见。
...T1 > T_max,说明T1比较晚,该行对当前事务不可见,根据DB_ROLL_PTR找到上一个判断再次判断。
...T_min <= T1 <= T_max,如果read_view中有该行数据事务id(T1),则不可见,根据DB_ROLL_PTR找上一个版本。如果不在,代表T1数据行是之前已提交(非活跃)的事务数据行版本则可见。
Repeatable read各级离别下判断算法:创建事务trx结构的时候,就生成了当前的global read view。

 注意:

Repeatable read与Read Commited两种隔离级别的判断逻辑是一样的,区别在于read_view的创建时期不一样,read committed (每次执行sql之前都重新创建)总是读最新一份快照数据,而repeatable read (事务就创建)始终读事务开始时创建的快照数据。所以Read Commited事务级别前后执行sql读取快照数据不一致就会导致不可重复读的问题,而Repeatable read在当前事务内读取的都是同一份快照数据,可以避免不可重复读的问题

 

实例

1)初始行 

 

 

 2)事务1更新操作(因为update会加排他锁X,所以undo log都是排队顺序的,不会出现两个事务并发增加undo log)

 

 3)事务2更新操作

  转载:https://www.jianshu.com/p/adb15359d924

 

posted @ 2021-03-14 00:26  迷走神经  阅读(83)  评论(0编辑  收藏  举报