首页 > 数据库 >MySQL笔记之一致性视图与MVCC实现

MySQL笔记之一致性视图与MVCC实现

时间:2023-04-07 16:36:55浏览次数:42  
标签:事务 MySQL 视图 生成 trx 版本 MVCC ReadView id

一致性读视图是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 log,V1、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级别下事务每次读操作都能读到已经提交的数据。

 

 

参考资料:

《高性能 MySQL》第一章第 4 节;

极客时间《MySQL 实战 45 讲》

 

 

标签:事务,MySQL,视图,生成,trx,版本,MVCC,ReadView,id
From: https://www.cnblogs.com/binyue/p/17296542.html

相关文章

  • 踩坑/docker桌面版安装mysql
     很久没安装了,忘记如何启动了。删掉了本地images,然后重新拉取镜像。5.7.5-m15是最新的,但是本地启动失败。后来换成8.0.32版本的就可以了。这里需要说下中间出的问题:因为国内拉取docker官网镜像有问题,换成国内的进行:https://dashboard.daocloud.io/;dockerpulldaocloud.io/l......
  • mysql+navicat安装配置教程
    一、MySQLl和Navicat的关系Mysql一个关系型数据库管理系统,由瑞典MysqlLAB公司开发,目前属于Oracle旗下产品,是目前最流行的关心型数据库管理系统之一。Navicat一个数据库管理工具,用可视化界面提供给用户操作Mysql数据库管理系统。记得我第一次安装Navicat之后,就以为......
  • mysql运维------主从复制
    1.概述主从复制是指将主数据库的DDL和DML操作通过二进制日志传到从库服务器中,然后在从库上对这些日志重新执行(也叫重做),从而使得从库和主库的数据保持同步。MySQL支持一台主库同时向多台从库进行复制,从库同时也可以作为其他从服务器的主库,实现链状复制。MySQL复制的有点主要包......
  • MySQL数据库与Nacos搭建监控服务
    目录Nacos部署项目环境快速开始nacos2.2.0版本配置说明MySQL部署安装方式Linux平台(CentOS-Stream-9)部署MySQL调试防火墙管理工具MySQL用户权限MySQL导入mysql-schema脚本Springboot项目构建项目环境项目构建Nacos联动测试Nacos监控(控制台)基本功能演示验证数据库表我相信有不少小......
  • uniapp修改数组对象属性,视图不刷新问题
    uniapp最大的坑遇到修改数组属性视图不更新的问题 有两种解决方法一:this.$forceUpdate();强制更新,这个确实在H5端更新了,但是微信小程序还是没有更新二:this.$set(),一样不行修改数组后视图依旧不刷新最后用$.elmit()方法在子组件修改父组件传给子组件的值达到父子组件双向......
  • Centos7使用systemctl管理mysql8服务开机启动
    centos7下开机默认不执行原来配置启动命令的/etc/rc.local文件,建议使用systemctl管理自启动服务,如果要使用/etc/rc.local进行自启动,需要给文件/etc/rc.d/rc.local添加可执行权限。    systemctl常用命令如下:1.列出所有启动项命令systemctllist-unit-files开启的和未开启的......
  • 力扣1050(MySQL)-合作过至少三次的演员和导演(简单)
    题目:ActorDirector 表: 写一条SQL查询语句获取合作过至少三次的演员和导演的id对 (actor_id,director_id)示例:  建表语句:1createtableifnotexistsactordirector_1050(actor_idint(3),director_idint(3),timestampint(3)primarykey);2truncatetable......
  • 力扣1045(MySQL)-买下所有产品的客户(中等)
    题目:Customer 表: Product 表:写一条SQL查询语句,从 Customer 表中查询购买了 Product 表中所有产品的客户的id。示例:  解题思路:建表语句:1createtableifnotexistscustomer_1045(customer_idint(3)notnull,product_keyint(3));2createtableif......
  • 力扣627(MySQL)-变更性别(简单)
    题目:Salary 表:请你编写一个SQL查询来交换所有的'f'和'm'(即,将所有'f'变为'm',反之亦然),仅使用单个update语句,且不产生中间临时表。注意,你必须仅使用一条update语句,且不能使用select语句。查询结果如下例所示。示例1: 来源:力扣(LeetCode)链接:https://leet......
  • MYSQL基础知识之多表查询
    1、多表关系在数据表中,各个表结构之间存在着各种关系(一对一、一对多、多对多)。一对一关系:示例:学生与学生详情的关系,一个学生对应一个详细情况,一个详细情况对应一个学生。实现:在任意一方加入外键,关联另外一方的主键,并且设置外键为唯一的UNIQUE。一对多关系:示例:学生与班级的关......