Mysql神乎乎的MVCC到底该怎么理解

本文涉及的产品
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
云数据库 RDS PostgreSQL,集群系列 2核4GB
简介: MVCC即多版本并发控制主要是为了解决数据库中并发事务读写的一致性问题,那么多个事务并发执行的时候事务的隔离到底是怎么实现的呢?Mysql默认的RR隔离级别是怎样避免不可重复读的问题呢?我们好好来分析一下。

引言

MVCC即多版本并发控制主要是为了解决数据库中并发事务读写的一致性问题,那么多个事务并发执行的时候事务的隔离到底是怎么实现的呢?Mysql默认的RR隔离级别是怎样避免不可重复读的问题呢?我们好好来分析一下。

  • 什么是undo log多版本链
  • MVCC如何保证事务隔离
  • 总结


一、什么是undo log多版本链

Mysql的MVCC机制,以undo log版本链为实现基础。因此要理解MVCC机制,我们得先分析下undo log版本链是个什么东东。Innodb存储引擎给每个数据表都添加了三个隐藏字段:DB_TRX_ID、DB_ROLL_PTR、DB_ROW_ID。

(1)DB_TRX_ID: 标记更新当前数据记录的transaction id,每处理一个事务,其值自动+1。

(2)DB_ROLL_PTR: 回滚指针,记录了最新一次修改该条记录的undo log,回滚的时候就通过这个指针找到undo log回滚。

(3)DB_ROW_ID: 当数据表没有指定主键时,数据库会自动以这个列来作为主键,生成聚集索引。

假设有如下的一条数据,此时这条数据对应的DB_TRX_ID为10,由于之前没有数据,因此回滚指针对应指向空地址。

image.png

每个事务都有自己的一个id,就像其身份证一样唯一标记该事务。当事务启动的时候,向Innodb存储引擎进行申请。假设此时如果打南边来了个事务A,它的事务id为12,事务A对表中的数据字段count进行修改,修改后该条数据对应的事务id为12,同时回滚指针指向实际的undo log回滚日志的地址。

image.png

此时打北边又来了个事务B,它的事务id为20,事务B将表中的数据字段count修改为21,对应数据的事务id变为20,回滚指针指向上一条undo log信息。如下图所示:

image.png

如果一直有事务进行数据的修改,那么就会形成一条由回滚指针串联的undo log多版本链条。

二、MVCC如何保证事务隔离

阐述完了undo log多版本链条原理,我们知道当一个事务A事务id=12)更新数据后,当前数据的事务id变为12,同时回滚指针指向undo log数据。每次进行数据更新后,事务id就是修改数据的事务id,同时回滚指针指向回滚数据,最终形成undo log链。但是仅仅依靠undo log多版本链好像并不能实现事务并发执行时的相互隔离,因此我们需要一种机制可以利用undo log多版本链来实现事务隔离。这个机制就是ReadView。

Mysql执行事务的时候,会生成一个ReadView,其中会包含以下重要信息:


(1)m_ids:mysql中未提交的事务id集合;


(2)min_trx_id:集合中最小的事务id;


(3)max_trx_id,mysql下一个要生成的事务id,也就是事务id集合中最大的事务id加1;


(4)当前需要执行的事务id;


下面我们来说说Mysql的RR(Repeatable Read )隔离级别即可重复读,读取数据的事务,无论读多少次都是和第一次读取数据获得的值时一样的。我们一起来看下可重复读是如何通过MVCC实现的。 假设现在有事务A以及事务B两个事务,A事务需要读取数据,B事务需要修改数据。

image.png

当事务A需要读取数据时,开启ReadView。由于此时数据库活跃的事务为事务A以及事务B,那么对应的ReadView中m_ids={12,34},min_trx_id=12,max_trx_id=35,当前需要执行的事务id为12。此时事务A读取数据时,先判断当前的事务id为12,而数据中的事务id为11,小于当前事务A的id。说明当前读取的数据是在事务A开启之前提交的,因此可以正常进行数据读取。

image.png

如果此时事务B进行了数据修改,修改count为29。而事务A再次进行数据读取时,继续进行判断,发现当前数据对应的事务id为34比当前的查询事务要大,但是小于max_trx_id,同时在m_ids中。说明该事务id对应的事务和事务A属于并发执行事务,因此不能进行数据读取。则根据undo log版本链,往上寻找undo log信息。如果找到的事务id小于当前读取数据的id则证明此时的数据是在当前开启查询事务之前提交的,因此可以进行数据的查询。

image.png

那么另外一个问题又来了,RC级别又是如何实现的呢?所谓RC级别,就是当别人的事务提交后,你就可以读取到别人修改后的值。因此会发生不可重复读问题。当设置为事务级别为RC时,它每次发起数据查询(set session transaction isolation level read committed;)后,每次进行数据查询都会新开启一个新的ReadView。


假设当前事务中活跃着两个事务,他们的事务id分别是12、34。此时事务id为34的事务更新了数据。此时数据更新为29。同时数据对应的事务id更新为34,同时回滚指针指向上一条数据。若此时事务id为15的事务进行数据查询,此时开启readview,进行检查,发现此时的数据中对应的事务id在活跃事务id中,说明是和查询事务差不多时机执行的,但是此时的事务还未提交。因此此时的数据不可以读,所以顺着undolog版本链条读取上一次的数据。同时进行判断。


如果事务B进行了提交,那么事务A再次进行数据查询的时候,会新开启一个ReadView,我们暂且称之为ReadViewA1,由于此时的事务B已经提交,所以ReadViewA1中对应的活跃列表中只有事务A对应的事务id为12。此时发现事务已提交,不再活跃事务列表中,因此可以进行数据读取。

image.png

综上分析,这就是Mysql通过ReadView以及undo log多版本链条实现RC以及RR的秘密。RC以及RR的区别就在于,RC事务隔离级别下,每次获取数据的时候,都会重新生成新的ReadView,再根据ReadView中的信心进行数据读取的判断。

三、总结

综合以上的分析我们大致理清楚了Mysql多事务并发的隔离原理,其本质是通过MVCC机制来进行实现的。而MVCC其实是基于ReadView以及undo log多版本链条实现。Mysql的默认隔离级别是RR,避免了脏读、不可重复读以及幻读的问题。

相关实践学习
如何在云端创建MySQL数据库
开始实验后,系统会自动创建一台自建MySQL的 源数据库 ECS 实例和一台 目标数据库 RDS。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助     相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
相关文章
|
21天前
|
存储 关系型数据库 MySQL
MySQL MVCC全面解读:掌握并发控制的核心机制
【10月更文挑战第15天】 在数据库管理系统中,MySQL的InnoDB存储引擎采用了一种称为MVCC(Multi-Version Concurrency Control,多版本并发控制)的技术来处理事务的并发访问。MVCC不仅提高了数据库的并发性能,还保证了事务的隔离性。本文将深入探讨MySQL中的MVCC机制,为你在面试中遇到的相关问题提供全面的解答。
58 2
|
21天前
|
存储 关系型数据库 MySQL
MySQL MVCC深度解析:掌握并发控制的艺术
【10月更文挑战第23天】 在数据库领域,MVCC(Multi-Version Concurrency Control,多版本并发控制)是一种重要的并发控制机制,它允许多个事务并发执行而不产生冲突。MySQL作为广泛使用的数据库系统,其InnoDB存储引擎就采用了MVCC来处理事务。本文将深入探讨MySQL中的MVCC机制,帮助你在面试中自信应对相关问题。
63 3
|
5月前
|
存储 关系型数据库 MySQL
MySQL数据库进阶第六篇(InnoDB引擎架构,事务原理,MVCC)
MySQL数据库进阶第六篇(InnoDB引擎架构,事务原理,MVCC)
|
2月前
|
关系型数据库 MySQL 数据库
MySQL高级篇——MVCC多版本并发控制
什么是MVCC、快照读与当前读、隐藏字段、Undo Log版本链、ReadView、举例说明、InnoDB 解决幻读问题
MySQL高级篇——MVCC多版本并发控制
|
3月前
|
SQL 关系型数据库 MySQL
Mysql原理与调优-事务与MVCC
【8月更文挑战第19天】
|
4月前
|
SQL 存储 关系型数据库
(九)MySQL之MVCC机制:为什么你改了的数据我还看不见?
在《MySQL锁机制》这篇文章中,咱们全面剖析了MySQL提供的锁机制,对于并发事务通常可以通过其提供的各类锁,去确保各场景下的线程安全问题,从而能够防止脏写、脏读、不可重复读及幻读这类问题出现。
111 0
|
3月前
|
关系型数据库 MySQL 数据库
MySQL MVCC和间隙锁有什么区别?
【8月更文挑战第24天】MySQL MVCC和间隙锁有什么区别?
88 0
|
4月前
|
存储 关系型数据库 文件存储
面试题MySQL问题之简单的SELECT操作在MVCC下加锁如何解决
面试题MySQL问题之简单的SELECT操作在MVCC下加锁如何解决
47 2
|
4月前
|
关系型数据库 MySQL
面试题MySQL问题之Read uncommitted隔离级别不适用MVCC如何解决
面试题MySQL问题之Read uncommitted隔离级别不适用MVCC如何解决
45 1
|
5月前
|
关系型数据库 MySQL
mysql事务隔离级别MVCC
mysql事务隔离级别MVCC