一文彻底弄懂MySQL的MVCC多版本控制器
InnoDB 的 MVCC(Multi-Version Concurrency Control,多版本并发控制) 是 MySQL 实现高并发事务处理的一种机制。通过 MVCC,InnoDB 可以在高并发环境下支持 事务隔离,并提供 非阻塞的读操作,从而避免锁定所有读操作带来的性能瓶颈。MVCC 允许事务在不加锁的情况下读取数据,保证了性能和一致性。
一、MVCC 基础概念
MVCC 的核心思想是 通过保存数据的多个版本 来支持并发读写。每个事务在读取数据时看到的是某个数据的特定版本,而不是当前最新的值。这个机制依赖于 Undo Log,通过保存每一行记录的历史版本来支持多版本读取。(undolog)
- 读写分离:MVCC 的主要特性是读取数据不阻塞写操作,写操作也不阻塞读取操作。实现了读写分离,提升了数据库并发处理能力。
- 时间戳版本管理:每个事务都有一个唯一的 事务 ID(Transaction ID,简称
trx_id),InnoDB 使用事务 ID 来区分数据的不同版本。

二、MVCC 读操作的两种类型
- 快照读(Snapshot Read):读取的是历史版本的数据,是不加锁的普通读取操作。快照读是 MVCC 实现并发读的基础。
- 比如
SELECT * FROM table WHERE id = 1;,执行的是不加锁的快照读操作。
- 比如
- 当前读(Current Read):读取的是最新版本的数据,并加锁保证数据的一致性和事务隔离。当前读通常伴随着写操作。
- 比如
SELECT * FROM table WHERE id = 1 FOR UPDATE;,执行的是加锁的当前读操作。
- 比如
三、MVCC 的工作原理
InnoDB 通过 行版本控制 来管理数据的不同版本。每一行数据在 InnoDB 的行记录中都包含两个隐藏的字段:
- trx_id:表示最后一次对该行进行修改的事务 ID。
- roll_pointer:指向该行之前的版本(即 Undo Log 中的记录),通过该指针可以找到数据的历史版本。
1. 事务的开始与结束
- 每个事务在开始时会生成一个唯一的事务 ID
trx_id。 - 在事务读取数据时,InnoDB 会根据 MVCC 机制判断该事务应该看到哪个版本的数据,主要依赖于事务的隔离级别(如
Read Committed或Repeatable Read)。
2. 数据的修改与版本管理
当一个事务修改数据时,InnoDB 会将当前数据的旧版本保存到 Undo Log 中,并在数据行中更新最新的 trx_id 和 roll_pointer。这样即使数据被更新,其他未提交的事务依然可以通过 Undo Log 访问到旧版本的数据。
每行数据都会有多个历史版本,并通过 roll_pointer 链接到这些历史版本。
3. 版本链
版本链是基于 trx_id 和 roll_pointer 建立的,即每次修改数据时,会在 Undo Log 中存储旧版本,行记录会指向旧版本。版本链的结构如下:
最新记录 <-- trx_id_x --trx_id_y --trx_id_z... --> 历史版本
当事务读取数据时,会根据事务的隔离级别、当前事务的 trx_id 以及数据的 trx_id 来决定应该读取哪个版本。
四、MVCC 与事务隔离级别的关系
InnoDB 的 MVCC 机制在不同的事务隔离级别下有不同的行为表现:
- Read Committed(读取已提交):事务只会看到其他事务已经提交的版本,每次查询都会读取最新的已提交数据。这种隔离级别下,事务间存在不可重复读问题。
- 每次查询时,InnoDB 都会返回当前已经提交的最新版本数据。
- Repeatable Read(可重复读,MySQL 默认隔离级别):事务在整个过程中看到的是同一个版本快照的数据,即便有其他事务提交了新的数据,当前事务依然看到自己开始时的一致性快照。
- 事务开始时,InnoDB 会为事务创建一个 一致性视图(consistent view),之后的所有查询都会返回该视图中的数据,保证了可重复读。
隔离级别与 MVCC 读方式的关系
- Read Committed:每次读取都基于当前已经提交的最新版本,因此快照读是每次返回最新的数据。
- Repeatable Read:快照读总是基于事务启动时的版本快照,因此即便其他事务提交了新的数据,当前事务依然看到的是旧数据,直到它自己提交。
五、MVCC 的实现细节
1. 事务 ID 与版本控制
InnoDB 使用事务 ID(trx_id)来区分不同事务对数据的修改。每次修改都会将当前事务的事务 ID 记录在该行数据的 trx_id 字段中。通过事务 ID,InnoDB 可以判断当前事务是否能够看到某一行数据的特定版本。
2. 一致性视图
一致性视图(Consistent Read View)是指当前事务只能看到事务启动时的数据快照,除非事务使用的是当前读。InnoDB 会根据当前事务的事务 ID 和一致性视图来确定读取哪一个版本的数据。
- 对于快照读:根据事务的开始时间戳、其他事务的提交情况,来判断该事务看到的是哪个版本的数据。
- 对于当前读:必须是最新的数据,InnoDB 会为当前事务加锁,防止其他事务修改或读取。
3. Undo Log 与 Rollback Segment
当一个事务修改数据时,InnoDB 会将原始的数据版本存入 Undo Log 中,Undo Log 中记录了数据的历史版本。通过 roll_pointer,InnoDB 可以在发生并发时,允许其他事务读取数据的旧版本。
六、MVCC 的实际应用场景
1. 电商系统的订单查询
在电商系统中,用户在事务 A 中查询订单时,订单数据可能会被其他事务修改或插入新记录。通过 MVCC,事务 A 查询时看到的订单数据是一致的,即便其他事务插入了新的订单,事务 A 依然能看到一个稳定的订单视图。
2. 金融系统的账户余额查询
在金融系统中,用户账户余额的查询需要确保每次查询得到的结果一致,即使账户余额在后台因某些事务而发生变化,用户也能看到一贯的账户信息,保证用户体验的一致性。MVCC 在这种场景下能保证高并发下的数据一致性。
七、总结
- MVCC 是 InnoDB 实现高并发事务处理的重要机制,通过维护多版本数据和不加锁的快照读,解决了传统数据库加锁所带来的并发性能问题。
- MVCC 结合事务的隔离级别,保证数据的 一致性 和 隔离性,使得 MySQL 在高并发场景下依然能保持较高的性能。
- 通过事务 ID、Undo Log、一致性视图等机制,InnoDB 能够高效地管理事务间的数据访问,从而避免常见的并发读写问题,例如 幻读、不可重复读 等。
一文彻底弄懂MySQL的MVCC多版本控制器的更多相关文章
- 一文彻底读懂MySQL事务的四大隔离级别
前言 之前分析一个死锁问题,发现自己对数据库隔离级别理解还不够清楚,所以趁着这几天假期,整理一下MySQL事务的四大隔离级别相关知识,希望对大家有帮助~ 事务 什么是事务? 事务,由一个有限的数据库操 ...
- mysql的MVCC多版本并发控制机制
MVCC多版本并发控制机制 全英文名:Multi-Version Concurrency Control MVCC不会通过加锁互斥来保证隔离性,避免频繁的加锁互斥. 而在串行化隔离级别为了保证较高的隔 ...
- 超干货!为了让你彻底弄懂MySQL事务日志,我通宵肝出了这份图解!
还记得刚上研究生的时候,导师常挂在嘴边的一句话,"科研的基础不过就是数据而已."如今看来,无论是人文社科,还是自然科学,或许都可在一定程度上看作是数据的科学. 倘若剥开研究领域的外 ...
- 熬夜肝出5大点,18张图带你彻底弄懂MySQL事务日志
在当今社会,充斥着大量的数据.从众多APP上的账户资料到银行信用体系等个人档案,都离不开对大量数据的组织.存储和管理.而这,便是数据库存在的目的和价值.目前数据库的类型主要分为两种,一种是关系型数据库 ...
- 一文彻底搞懂MySQL分区
一个执着于技术的公众号 一.InnoDB逻辑存储结构 首先要先介绍一下InnoDB逻辑存储结构和区的概念,它的所有数据都被逻辑地存放在表空间,表空间又由段,区,页组成. 段 段就是上图的segment ...
- 一文快速搞懂MySQL InnoDB事务ACID实现原理(转)
这一篇主要讲一下 InnoDB 中的事务到底是如何实现 ACID 的: 原子性(atomicity) 一致性(consistency) 隔离性(isolation) 持久性(durability) 隔 ...
- 一文彻底弄懂cookie、session、token
前言 作为一个JAVA开发,之前有好几次出去面试,面试官都问我,JAVAWeb掌握的怎么样,我当时就不知道怎么回答,Web,日常开发中用的是什么?今天我们来说说JAVAWeb最应该掌握的三个内容. 发 ...
- 一文彻底弄懂this关键字用法
哈喽,大家好,我是指北君. 介绍完 native.static.final 关键字后,指北君再接再厉,接着为大家介绍另一个常用的关键字--this. this 也是Java中的一个关键字,在<J ...
- 针对MySQL的MVCC多版本并发控制的一些总结
MVCC MVCC细节太多,我直接备忘一下总结: MVCC就是通过事务的ID与行数据的版本(修改事务的ID)进行比较(通过redo log可以回溯版本)得出哪些版本的行数据可见和不可见而实现的事务隔离 ...
- 【MySQL】面试官:谈谈你对Mysql的MVCC的理解?
MVCC(Mutil-Version Concurrency Control),就是多版本并发控制.MVCC 是一种并发控制的方法,一般在数据库管理系统中,实现对数据库的并发访问. 在Mysql的In ...
随机推荐
- 低端hdmi视频采集卡的替代方案——向日葵远控
前一阵看直播推货入手了一款hdmi视频采集卡,如下: ======================================================= 使用这个视频采集卡发现两个问题: ...
- 多线程之深入理解park与unpark
1.背景 面试官问,如何暂停一个线程勒..... 说说你对park的理解....... 2.代码 package com.ldp.demo01; import com.common.MyThreadU ...
- SemanticKernel/C#:实现接口,接入本地嵌入模型
前言 本文通过Codeblaze.SemanticKernel这个项目,学习如何实现ITextEmbeddingGenerationService接口,接入本地嵌入模型. 项目地址:https://g ...
- Apache DolphinScheduler 与 AWS 的 EMR/Redshift 集成实践分享
引言 这篇文章将给大家讲解关于DolphinScheduler与AWS的EMR和Redshift的集成实践,通过本文希望大家能更深入地了解AWS智能湖仓架构,以及DolphinScheduler在实际 ...
- 推荐一款Python开源移动应用安全测试分析工具!!!
今天给大家推荐一个安全测试相关的开源项目:nccgroup/house 1.介绍 它是一个由 NCC Group 开发的,一个基于Frida和Python编写的动态运行时移动应用分析工具包,提供了基于 ...
- quartz执行卡死--强制中断线程
在quartz中经常会碰到由于网络问题或者一些其他不稳定因素导致的线程卡死问题,这往往会导致数据处理的延时.而有时候一时无法定位到卡死的原因,为了降低系统风险,我们就会希望有一个超时机制,当执行超时时 ...
- Linux 进程编程入门
关于进程和线程的关系,之前一口君写过这几篇文章,大家可以参考下. 本文从头带着大家一起学习Linux进程 <搞懂进程组.会话.控制终端关系,才能明白守护进程干嘛的?> <[粉丝问答6 ...
- Tree组件的快速定位更新节点的状态,以及修改节点的数据属性等操作
当我们点击树节点的时候我们常常只能获得树的id,那么我么如何获快速定位到树节点的内容呢,除此之外,当树已经存在时,但是缺少我们想要的内容时,我们想在树节点上添加我们需要的额外的内容时该怎么办,那么就是 ...
- protostuff序列化接口封装
1.pom <dependency> <groupId>com.dyuproject.protostuff</groupId> <artifactId> ...
- PageHeper
PageHelper 是一个非常流行的 MyBatis 分页插件,主要用于简化分页查询的实现.使用 PageHelper 可以在执行数据库查询时,自动处理分页参数,从而避免手动编写繁琐的分页逻辑. 今 ...