首页 > 数据库 >如何理解MySQL的MVCC多版本并发控制

如何理解MySQL的MVCC多版本并发控制

时间:2023-04-03 23:35:33浏览次数:32  
标签:事务 快照 trx MySQL 并发 MVCC ReadView id

前言

我们知道在mysql中存在四种隔离级别(读未提交、读已提交、可重复读、序列化),它默认的就是隔离级别就是可重复读,它能够解决脏读、不可重复读问题,并且在innodb引擎下能部分解决幻读问题。在mysql innodb存储引擎下RC(读已提交),RR(可重复读)基于MVCC(多版本并发控制)进行并发事务控制。那我来了解一下它是如何实现的。

MVCC(多版本并发控制)

MVCC是基于”数据版本“对并发事务进行访问

这里有4个操作ABCD,事务id分别为1、2、3、4

  1. 事务A执行的操作是将id为1088的name更新为张三后提交
  2. 事务B执行的操作在事务A commit后将name更新为张小三后提交
  3. 事务C执行的操作是在事务B执行完成后将name更新为张老三后提交
  4. 事务D执行的两次查询,第一次是在事务B update后 但是还没commit的时候进行的一次查询,第二次是在事务C update后还未commit前进行的一次查询。

针对于D的这两次查询如果是在RR级别(可重复读)第一次跟第二次查询的结果都为张三,如果是在RC级别(读已提交)第一次为张三,第二次为张小三。在RC级别下出现了”不可重复读“

版本链

为什么会出现这种情况呢,其实在innodb模式下有一个基于undo_log的版本链

最上面一行是表中当前数据,而且它会在这条数据上面额外添加两个字段,TRX_ID 最后一次更新的事务ID,DB_ROLL_PTR则是记录者上一次版本变化的那条记录地址。最后一条为最原始的数据,所以没有事务编号跟上次记录的地址。mysql的回滚就是根据undo_log版本链来进行回滚操作。并且mysql在确保版本链数据不再被引用后会进行删除。

ReadView

ReadView是”快照读“SQL执行时MVCC提取数据的依据。快照读就是最普通的select查询语句。而与之相对应的还有一个当前读,指的是执行 insert、update、delete、select ... for update(写锁/排它锁) 、 select ... lock in share mode(读锁/共享锁)

ReadView是一个数据结构,包含四个字段

  1. m_ids:当前活跃的事务编号集合
  2. min_trx_id:最小活跃事务编号
  3. max_trx_id:预分配事务编号,当前最大事务编号+1
  4. creator_trx_id:ReadView创建者的事务编号

在RC模式下,在每一次执行快照读的时候生成ReadView

如图:在第一次快照读的时候因为A已经提交了,所以当前活跃的事务为BCD,m_ids为2,3,4。最小活跃的事务id为2,预分配的事务id为5,创建者的id为4。在进行第二次快照读的时候,事务B已经commit掉了这个时候活跃的事务为CD,那么m_ids为3,4,并且最小的事务id为3。

接下来我们来分析一下MVCC是如何基于ReadView进行数据提取的。版本链数据访问有几个规则:

  1. 判断当前的事务id等于creator_trx_id吗?如果成立说明数据就是这个事务更改的,可以访问。
  2. 判断trx_id<min_trx_id吗?如果成立说明数据已经提交了,可以访问。
  3. 判断trx_id>max_trx_id吗?如果成立说明该事务实在ReadView生成以后才开启的,则不允许访问。
  4. 判断min_trx_id<= trx_id<=max_trx_id?如果成立则在m_ids数据中对比,不存在则代表数据是已经提交过后的,则可以访问。

我们来进行第一次查询分析,第一条数据trx_id为3,而ReadView中的creator_trx_id为4,所以不符合第一个条件。并且trx_id大于min_trx_id(2),所以第二个条件也不符合。并且也不大于max_trx_id(5)所以第三个也不符合,最后虽然它的trx_id(3)大于min_trx_id(2) 小于max_trx_id(5),但是它存在于m_ids(2,3,4)中,则说明这条数据不符合条件然后继续代入下一条数据进行判断。对比下来发现张三这条数据 trx_id 为1符合我们的条件所以返回这条数据。

第二次查询也是一样的,代入ReadView进去对比,发现得到的结果为张小三。

我们通过这张图也可以验证我们推导的结果,第一次的查询返回的是张三这条数据,第二次返回的是张小三的这条数据。

这也验证了在RC模式下,两次读取到的结果不一致,是不可重复读。

可重复读(RR):仅在第一次执行快照读的时候生成ReadView,后续快照读复用。

所以在这种ReadView、版本链、判断规则都没有发生变化的情况下,两次读取到的数据当然是一样的,所以也就不会有不可重复读的问题。

RR级别下使用MVCC能在一定程度上解决幻读的问题,并不能完全解决。因为MVCC并不是采用锁的机制对事务数据做了隔离,而是通过版本控制变相解决幻读的问题。

在连续多次快照读下,ReadView会产生复用,没有幻读的问题。

但是在两次快照读之间存在当前读,并且覆盖到了其他事务变更的数据,ReadView会重新生成,导致幻读的产生。

如图在事务B中第一次查询到只有一条结果,这个时候会生成一个ReadView,然后事务A新插入一条数据后。这个时候事务B执行了update操作,这会产生一次当前读,并且会重新生成ReadView,最后再查询则出现了2条数据,产生了幻读。

标签:事务,快照,trx,MySQL,并发,MVCC,ReadView,id
From: https://www.cnblogs.com/loveletters/p/mysql-mvcc.html

相关文章

  • MYSQL基础知识之DQL语句
    1、DQL概念DQL英文全称是DataQueryLanguage(数据查询语言),用来查询数据库中的表的记录2、基本查询语法:#查询全部字段SELECT*FROM表名; #查询多个字段SELECT字段1,字段2,字段3...FROM表名; #去重 语法:SELECTDISTINCT字段列表FROM表名;   3、条......
  • 【Java 并发】【八】【Atomic】【二】AtomicInteger、AtomicBoolean原理
    1 前言这节我们从AtomicInteger这个比较简单的原子类开始,来看看AtomicInteger的底层原理。2  实测样例对比线程安全性在说AtomicInteger的底层原理之前呢,我们先来看个例子感受下原子类:static修饰的共享变量,我们开启两个线程对共享变量进行10000次+1的操作2.1  Integer......
  • Mysql基本语句
    创建用户三种方式:CREATEUSERusername1IDENTIFIEDBY'password';CREATEUSER'username1'@'localhost'IDENTIFIEDBY'password';在MySQL中,可以使用password()函数获取密码的哈希值,查看test1哈希值的SQL语句和执行过程如下:mysql>SELECTpassword(�......
  • MySQL(九)InnoDB行格式
    InnoDB行格式查看默认行格式:select@@innodb_default_row_format;查看数据库表使用的行格式mysql>useatguigudb;ReadingtableinformationforcompletionoftableandcolumnnamesYoucanturnoffthisfeaturetogetaquickerstartupwith-ADatabasechanged......
  • MySQL(九)InnoDB数据结构
    InnoDB数据结构1数据库的存储结构:页​ 索引信息和数据记录都是保存在文件上的,确切来说是保存在页结构中;另一方面,索引是在存储引擎上实现的,MySQL服务器上的存储引擎负责对表中数据的读取和写入工作。不同的存储引擎的存放格式是不同的,比如Memory甚至不使用磁盘进行存储数据。......
  • MySQL(十)表空间结构:区、段与碎片区
    表空间结构:区、段与碎片区为什么要有区?​ B+树中的每一层的页都会形成一个双向链表,双向链表之间的物理位置可能会离得非常远,当遇到范围查询的适用场景的时候,就会定位到最左边和最右边的记录,然后沿着双向链表一直扫描,而如果这其中的两个页面物理上离得特别远,就会成为随机I/O,由于......
  • 【Java 并发】【八】【Atomic】【一】JUC下的Atomic原子类体系概览
    1 前言这节我们就开始看看Atomic原子类系列,JUC包下提供的原子类底层的实现原理基本都是差不多的,都是基于volatile和CAS操作来保证线程安全的,我们后续会着重分析几个类。2  概览我们看下JUC下边都有哪些原子类:看上面的图形,我们使用红色圈中的那些,就是我们要着重讨论的,一共......
  • MYSQL基础知识之DDL语句
    一、DDL概念DDL(DataDefinitionLanguage)语言:数据定义语言,用来定义数据库对象,如数据库、数据表和数据字段,主要是进行定义/改变表的结构、数据类型、表之间的链接等操作。常用的语句关键字有CREATE、DROP、ALTER等。 二、数据库操作2.1、linux环境连接数据库语法:mysql-u用......
  • 第七章:并发编程
    第七章:并发编程目录第七章:并发编程一、并发与并行二、Go协程(Goroutine)1Go协程介绍2启动Go协程3GMP调度模型三、信道(Channel)1信道使用2死锁现象3单向信道【了解】4关闭信道5循环信道四、缓冲信道1缓冲信道2WaitGroup五、select六、mutex七、异常处理一、并发与并行并......
  • Mysql主从复制
    工作原理图:主从复制的原理:分为同步复制和异步复制,实际复制架构中大部分为异步复制。复制的基本过程如下:1).Slave上面的IO进程连接上Master,并请求从指定日志文件的指定位置(或者从最开始的日志)之后的日志内容;2).Master接收到来自Slave的IO进程的请求后,通过负责复制的IO进程根据请......