首页 > 数据库 >Mysql中mvcc实现原理

Mysql中mvcc实现原理

时间:2023-10-15 10:56:47浏览次数:51  
标签:事务 READ Mysql trx mvcc 版本 ReadView 原理 id

Mysql中mvcc实现原理

今天我们简单来介绍一下mvcc的实现原理。官方文档的链接也贴在这里官方文档


mvcc全称Multi-Version Concurrency Control ,多版本并发控制,顾名思义是维持了数据库中数据的多版本;这个机制主要是为了服务事务隔离级别中的READ COMMITTED和REPATEABLE READ两种隔离级别在多个事务读取数据的时候能遵守sql标准。


对于innodb存储引擎来说,每一条记录默认都会生成两个隐藏字段

  • trx_id :每次一个事务对某条聚簇索引记录进行改动时,都会把该事务的事务id 赋值给trx_id 隐藏列。
  • roll_pointer :每次对某条聚簇索引记录进行改动时,都会把旧的版本写入到undo日志 中,然后这个隐藏列就相当于一个指针,可以通过它来找到该记录修改前的信息。

我们在表里插入一条数据

实际上这条记录的示意图如下

可以看到,一条记录里面除了我们定义的基础字段之外,还多了trx_id和roll_pointer两个字段,undo日志里面的插入日志比较特殊,这类日志主要是为了事务回滚时能够撤销操作;在事务已经提交后,已经不能把记录回滚了,所以插入undo日志会被删除或者对应的空间会被重新分配,所以对应记录的roll_pointer指针指向的值其实已经是无效的。

假设之后两个事务id 分别为100 、200 的事务对这条记录进行UPDATE 操作,操作流程如下:

每次对记录进行改动,都会记录一条undo日志 ,每条undo日志也都有一个roll_pointer 属性(INSERT 操作对应的undo日志 没有该属性,因为该记录并没有更早的版本),可以将这些undo日志 都连起来,串成一个链表,所以现在的情况就像下图一样:

到这里其实我们也可以进行一些猜测了,因为每条记录都记录了自己的一个版本链,而每个版本可以使用事务id来表示本次版本的改动是哪个事务执行的,在事务隔离级别中,区别就在于不同隔离级别的事务能读到哪些记录。

READ VIEW

在mysql中,对于事务中开启的读取操作,介绍一个READ VIEW的概念。ReadView 中主要包含4个比较重要的内容:

  • m_ids :表示在生成ReadView 时当前系统中活跃的读写事务的事务id 列表。
  • min_trx_id :表示在生成ReadView 时当前系统中活跃的读写事务中最小的事务id ,也就是m_ids 中的最小值。
  • max_trx_id :表示生成ReadView 时系统中应该分配给下一个事务的id 值。小贴士: 注意max_trx_id并不是m_ids中的最大值,事务id是递增分配的。比方说现在有id为1,2,3这三个事务,之后id为3的事务提交了。那么一个新的读事务在生成ReadView时,m_ids就包括1和2,min_trx_id的值就是1,max_trx_id的值就是4。
  • creator_trx_id :表示生成该ReadView 的事务的事务id 。小贴士: 我们前边说过,只有在对表中的记录做改动时(执行INSERT、DELETE、UPDATE这些语句时)才会为事务分配事务id,否则在一个只读事务中的事务id值都默认为0。

根据一定的步骤查看某个事务对某条记录是否可见,有了这个ReadView ,这样在访问某条记录时,只需要按照下边的步骤判断记录的某个版本是否可见:如果被访问版本的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 时生成该版本的事务已经被提交,该版本可以被访问。如果某个版本的数据对当前事务不可不可见的话,那就顺着版本链找到下一个版本的数据,继续按照上边的步骤判断可见性,依此类推,直到版本链中的最后一个版本。如果最后一个版本也不可见的话,那么就意味着该条记录对该事务完全不可见,查询结果就不包含该记录。


在MySQL 中,READ COMMITTED 和REPEATABLE READ 隔离级别的的一个非常大的区别就是它们生成ReadView的时机不同 。

READ COMMITTED —— 每次读取数据前都生成一个ReadView

使用REPEATABLE READ隔离级别的事务在每次查询开始时都会生成一个独立的ReadView 。

比如READ COMITTED隔离级别下,每一次普通select语句都是生成最新的ReadView,假如在两次select之间,有一些事务对记录进行了改变或者一些事务已经提交,两次readView里面的信息肯定不一样,所以就会导致不可重复读的问题;与之相反,在REPEATABLE READ隔离级别下,同一个事务开启之后,在事务执行期间的普通select语句使用的都是同一个readView,自然也就能保证读取的记录都是一样的啦。

结论

从上边的描述中我们可以看出来,所谓的MVCC (Multi-Version Concurrency Control ,多版本并发控制)指的就是在使用READ COMMITTD 、REPEATABLE READ 这两种隔离级别的事务在执行普通的SEELCT 操作时访问记录的版本链的过程,这样子可以使不同事务的读-写 、写-读 操作并发执行,从而提升系统性能。READ COMMITTD 、REPEATABLE READ 这两个隔离级别的一个很大不同就是:生成ReadView的时机不同,READ COMMITTD在每一次进行普通SELECT操作前都会生成一个ReadView,而REPEATABLE READ只在第一次进行普通SELECT操作前生成一个ReadView,之后的查询操作都重复使用这个ReadView就好了 。

标签:事务,READ,Mysql,trx,mvcc,版本,ReadView,原理,id
From: https://www.cnblogs.com/ykmStudy/p/17765346.html

相关文章

  • 了解 MySQL 数据库的三大日志(redo log、undo log、binary log)
    前言MySQL中有以下几种日志,包括:redolog(重做日志)undolog(回滚日志)binarylog(二进制日志)errorlog(错误日志)slowquerylog(慢查询日志)generallog(一般查询日志)relaylog(中继日志)事务的特性:原子性(Atomicity):事务是最小的执行单位,不允许分割。事务的原子......
  • Windows上卸载MySQL 5.1
        完整的卸载MySQL5.1的卸载方法:1、控制面板里的增加删除程序内进行删除2、删除MySQL文件夹下的my.ini文件,如果备份好,可以直接将文件夹全部删除3、开始->运行->regedit看看注册表里这几个地方删除没有HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\S......
  • 深入理解 JavaScript 时间分片:原理、应用与代码示例解析
    JavaScript时间分片(TimeSlicing)是一种优化技术,用于将长时间运行的任务拆分为多个小任务,以避免阻塞主线程,提高页面的响应性和性能。本文将详细解释JavaScript时间分片的原理、应用场景,并通过代码示例帮助读者更好地理解和应用该技术。本文首发于:kelen.cc概念时间分片(TimeSl......
  • 重庆大学考研916微机原理及应用三831历年真题912参考答案初试辅导资料【全】
    重庆大学考研916微机原理及应用三831历年真题912参考答案初试辅导资料【全】重庆大学微机原理考研916微机原理及应用三912微机原理及应用二、831微机原理及应用一历年真题参考答案初试辅导资料获取链接:https://www.uu2id.com/950.html 资料含历年真题难点题目详细解析2......
  • vue style 原理
    vuestyle的实现主要通过css的属性选择器什么是属性选择器?答:用于判断标签属性的一种选择器<style>.a[self_attribute]{...}</style><!--生效--><divself_attributeclass="a"></div><!--不生效--><divclass="a"></div&......
  • 计算机组成原理5
    八、中断中断向量:提供中断服务程序的入口地址中断向量表:所有中断服务的入口地址中断响应时间:从发出中断请求到进入中断服务程序保存现场继续执行主程序  九、输入输出(IO)控制方式9.1、程序查询方式  9.2、中断驱动方式   9.3、DMA方式DMA......
  • 2023_10_14_MYSQL_DAY_05_笔记
    2023_10_14_MYSQL_DAY_05_笔记https://www.cnblogs.com/tdskee/p/16536166.html{MySQL的优化多种方法(至少15条)}#查看触发器showtriggers;#删除触发器droptrigger触发器名;#建立触发器droptriggerifexistsdept_del;createtriggerdept_delafterdeleteon......
  • 2023_10_14_MYSQL_DAY_06_MYSQL优化的种类
    MYSQL优化的种类MYSQL的优化,是每一个程序员在做数据查询处理的时候,经常有的步骤那么SQL的优化有很多种,它可以是在硬件方面的,可以是在代码层面的,可以是在数据库方面的优化。下面就详细整理一下30种优化MYSQL的方案:1.在读表的时候,尽可能的避免全表扫描,合理的根据业务需求,在wher......
  • mysql报错:You must reset your password using ALTER USER statement before executin
    新安装mysql后,登录后,执行任何命令都会报错:YoumustresetyourpasswordusingALTERUSERstatementbeforeexecutingthisstatement.【解决办法】MySQL版本5.7.6版本以前用户可以使用如下命令:mysql>SETPASSWORD=PASSWORD('Admin2022!');MySQL版本5.7.6版本开始的用户可以使......
  • arraylist扩容原理
    ArrayList是Java中的动态数组,其扩容原理是在元素数量超过当前数组容量时,创建一个更大容量的新数组,并将所有元素从旧数组复制到新数组。下面是ArrayList扩容的基本原理:初始容量:当你创建一个ArrayList对象时,它会有一个初始容量,通常为10。这个容量可以根据需要进行调整。元素添加:当你......