网站建设和制作,个人网站能做淘宝客吗,wordpress手机qq登录地址,宁波网络营销策划公司MySQL笔记之一致性视图与MVCC实现
一致性读视图是InnoDB在实现MVCC用到的虚拟结构#xff0c;用于读提交#xff08;RC#xff09;和可重复度#xff08;RR#xff09;隔离级别的实现。
一致性视图没有物理结构#xff0c;主要是在事务执行期间用来定义该事物可以看到什…MySQL笔记之一致性视图与MVCC实现
一致性读视图是InnoDB在实现MVCC用到的虚拟结构用于读提交RC和可重复度RR隔离级别的实现。
一致性视图没有物理结构主要是在事务执行期间用来定义该事物可以看到什么数据。 一、Read View
事务在正式启动的时候我们会创建一致性视图该一致性视图是基于整个库的。 1、transaction id InnodDB的每个事务都有一个唯一的事务ID叫做transaction id该ID在事务开始的时候向InnoDB申请并且按照申请顺序严格递增。
每行数据都会有多个版本每次事务更新数据的时候都会生成一个新的数据版本并且把transaction id赋值给这个数据版本的事务id称为row trx_id。 上图是一条行数据的多个版本最新的版本是 V4。
其中U3、U2、U1代表的是undo logV1、V2、V3在物理上并不真实存在而是在需要的时候通过V4配合undo log计算获得。 2、ReadView如何工作 ReadView中主要包含4个比较重要的内容
m_ids表示在生成ReadView时当前系统中活跃的读写事务的事务id列表。min_trx_id表示在生成ReadView时当前系统中活跃的读写事务中最小的事务id也就是m_ids中的最小值。max_trx_id表示生成ReadView时系统中应该分配给下一个事务的id值。creator_trx_id表示生成该ReadView的事务的事务id。 在访问某条记录时按照下边的步骤判断记录的某个版本是否可见
如果被访问版本的trx_id属性值与ReadView中的creator_trx_id值相同意味着当前事务在访问它自己修改过的记录所以该版本可以被当前事务访问。如果被访问版本的trx_id属性值小于ReadView中的min_trx_id值表明生成该版本的事务在当前事务生成ReadView前已经提交所以该版本可以被当前事务访问。如果被访问版本的trx_id属性值大于ReadView中的max_trx_id值表明生成该版本的事务在当前事务生成ReadView后才开启所以该版本不可以被当前事务访问。如果被访问版本的trx_id属性值在ReadView的min_trx_id和max_trx_id之间那就需要判断一下trx_id属性值是不是在m_ids列表中如果在说明创建ReadView时生成该版本的事务还是活跃的该版本不可以被访问如果不在说明创建ReadView时生成该版本的事务已经被提交该版本可以被访问。 3、记录未提交的场景 如果某个版本的数据对当前事务不可见的话那就顺着版本链找到下一个版本的数据继续按照上边的步骤判断可见性依此类推直到版本链中的最后一个版本。
如果最后一个版本也不可见的话那么就意味着该条记录对该事务完全不可见查询结果就不包含该记录。 二、不同隔离级别下生成ReadView区别
在MySQL中READ COMMITTED和REPEATABLE READ隔离级别的区别就是它们生成ReadView的时机不同。 1、可重复读隔离
MySQL的默认隔离级别是RR可重复读按照 可重复读的语义每个事务启动的时候只能看到已经提交的事务并且在本事务执行的过程中不可以读取到其他事务的更新操作。
在InnoDB 中为每个事务构造了一个 当前事务ID数组的快照就是记录事务开启时当前正在执行的事务ID 的集合。数组里面 trx_id 最小的记为 低水位trx_id 最大的 1 记为高水位。如下图所示 对于一个新事务而言所读取到的记录版本的 trx_id 可能有以下几种情况
1、在绿色区域说明数据版本在事务开始前已提交当前版本是可见的。
2、在红色区域说明数据版本在事务开始后变更的当前版本是不可见的。
3、在橙色区域包含 2 种情况。
A、如果 数据版本的 trx_id 在数组中说明是正在执行的事务不可见。
B、如果 数据版本的 trx_id 不在数组中说明是已经提交的事务可见。 可以看出InnoDB 利用了 UndoLog 数据多版本的特点实现了快速创建快照的能力。 2、读已提交 对可重复读来说事务只有在第一次进行读操作时才会生成一个ReadView后续的读操作都会重复使用这个ReadView。
也就是说如果在此期间有其他事务提交了那么对于可重复读来说也是不可见的因为对它来说事务活跃状态在第一次进行读操作时就已经确定下来后面不会修改了。
对读已提交来说事务中的每次读操作都会生成一个新的ReadView。
也就是说如果这期间某个未提交事务Commit了那么它就会从ReadView中移除添加到已提交事务中这样确保RC级别下事务每次读操作都能读到已经提交的数据。