当前位置: 首页 > news >正文

深入解析 MySQL MVCC:高并发背后的数据时光机

目录

前言

二、事务的隔离级别

三、MVCC的作用

1.提升并发性能

2.解决幻读问题(依赖于隔离级别)

3.非阻塞读

四、MVCC实现原理

1.必需的“隐藏字段”

2.核心组件:Undo Log

3.一致性视图:Read View

4.版本可见性规则

四、使用场景与局限性

使用场景

局限性

总结


前言

在现代数据库系统中,高并发处理能力是衡量其性能的关键指标。想象一下,当多个用户同时读写同一张表时,如何保证数据的一致性和隔离性,又能最大限度地提升并发性能?

MySQL的InnoDB存储引擎给出的核心答案之一就是MVCC。


一、MVCC是什么?

MVCC,全称 Multi-Version Concurrency Control,即多版本并发控制

它是一种高级的数据库并发访问控制技术,其核心思想是:为每条记录保存多个历史版本。当不同事务同时访问数据库时,每个事务看到的的符合其隔离级别的、某个时间点的数据库快照,而不是直接操作同一份数据本身。

你可以把 MVCC 想象成一个 “数据时光机” 。每个事务在启动时,都获得了某个时刻的数据状态“快照”。无论之后其他事务如何修改或提交数据,这个快照在该事务的生命周期内都是不变的。这样,读操作和写操作就无需互相等待,极大地提升了并发效率。

二、事务的隔离级别

在MVCC中,事务的隔离级别决定了事务如何定义它们的ReadView。主要的隔离级别包括:

  • 读未提交(READ UNCOMITTED:允许读取尚未提交的数据变更,可能会导致脏读、幻读或不可重复读。

  • 读已提交(READ COMMITTED:允许读取已经提交的数据,可能会导致幻读和不可重复读。

  • 可重复读(REPEATABLE READ:对同一字段的多次读取结果一致,除非数据是被本身事务自己所修改,可能会导致幻读。

  • 可串行化(REPEATABLE READ:最高隔离级别,事务之间完全串行执行。

MySQL 的事务的隔离级别由高到低,分别为SERIALIZABLE、REPEATABLE、READ COMMITTED、 READREAD UNCOMITTED。低级别的隔离级别可以支持更高的并发处理,同时占用的系统资源更少。

三、MVCC的作用

MVCC 的出现,主要为了解决传统锁机制带来的性能瓶颈,它带来了以下几个核心优势:

1.提升并发性能

  • 读写不阻塞:在 MVCC 下,普通的 SELECT 查询(快照读)不会被正在执行的 UPDATEDELETE 等写操作阻塞。反之亦然(在大多数情况下)。这打破了读写互斥锁的限制,使得系统能够支持更高的并发连接数。

2.解决幻读问题(依赖于隔离级别)

  • 在 可重复读(REPEATABLE READ) 隔离级别下,MVCC 通过一致性读视图(ReadView)保证了事务内多次读取同一范围的数据时,看到的结果是一致的,从而避免了“幻读”现象。

3.非阻塞读

  • 这是 MVCC 最直接的好处。大部分读操作无需申请锁,几乎像是无锁操作,使得查询速度非常快,对 OLTP(联机事务处理)场景至关重要。

四、MVCC实现原理

MVCC 的实现并不是一个单一的功能,而是 InnoDB 通过一系列隐藏字段、Undo Log(回滚日志) 和 Read View(读视图) 协同工作的结果。

1.必需的“隐藏字段”

InnoDB 为每行记录(聚集索引)添加了两个重要的隐藏字段:

  • DB_TRX_ID(6字节):事务ID。表示最近一次插入或更新该行记录的事务ID。DELETE 操作在 InnoDB 内部也被视为一次更新。

  • DB_ROLL_PTR(7字节):回滚指针。指向该行记录上一个历史版本的指针,这个历史版本存储在 Undo Log 中。

(此外,还有一个隐藏的 DB_ROW_ID 字段作为行ID,但与 MVCC 关系不大。)

2.核心组件:Undo Log

Undo Log 主要用来保证事务的原子性和回滚,同时也是 MVCC 实现多版本的关键。

  • 当一个事务更新某行数据时,会先将该行的原始数据复制一份到 Undo Log 中。

  • 然后用新的数据更新当前行,并更新 DB_TRX_ID 为当前事务ID,DB_ROLL_PTR 指向刚刚写入 Undo Log 的旧版本记录。

  • 旧版本记录的回滚指针又会指向更早的版本。这样,一行数据的所有历史版本就被 DB_ROLL_PTR 指针串成了一个版本链

3.一致性视图:Read View

Read View 是事务在执行快照读时产生的读视图。它决定了当前事务能看到哪个版本的数据。

Read View 主要包含以下关键信息:

  • m_ids:生成 Read View 时,系统中活跃的(未提交的)事务ID列表。

  • min_trx_idm_ids 中最小的事务ID。

  • max_trx_id:生成 Read View 时,系统尚未分配的下一个事务ID(即当前最大事务ID+1)。

  • creator_trx_id:创建该 Read View 的事务ID。

4.版本可见性规则

当一条记录有多个版本时,事务如何判断应该看到哪个版本?规则如下:
沿着版本链,对比每个版本的 DB_TRX_ID 和当前 Read View 中的属性:

  1. 如果 DB_TRX_ID < min_trx_id,说明该版本在 Read View 创建前已提交,可见

  2. 如果 DB_TRX_ID >= max_trx_id,说明该版本在 Read View 创建后才开启,不可见

  3. 如果 min_trx_id <= DB_TRX_ID < max_trx_id,则需要进一步判断:

    • 如果 DB_TRX_ID 在 m_ids(活跃事务列表)中,说明创建该版本的事务还未提交,不可见

    • 如果 DB_TRX_ID 不在 m_ids 中,说明创建该版本的事务已提交,可见

如果某个版本对当前事务不可见,就顺着回滚指针 DB_ROLL_PTR 找到上一个版本,重复上述判断规则,直到找到可见的版本为止。

RR隔离示例:

注意:对于 读已提交(READ COMMITTED) 和 可重复读(REPEATABLE READ) 隔离级别,生成 Read View 的时机不同:

  • RC每次执行快照读时都会生成一个新的 Read View。因此它能读到其他事务已提交的最新数据。

  • RR:只在第一次执行快照读时生成一个 Read View,后续所有读操作都复用这个视图。因此它看到的数据始终和第一次读时一致。

四、使用场景与局限性

使用场景

  1. 高并发读多写少的OLTP系统:如电商网站、论坛、SaaS应用等,读请求远多于写请求,MVCC 的非阻塞读特性优势巨大。

  2. 需要高一致性读的报告与分析:一个长时间运行的报表查询,即使背后数据在不断变化,它也能获得一个一致性的快照,保证数据准确性。

  3. 实现非锁定一致性备份:像 mysqldump --single-transaction 这样的工具,就是通过开启一个事务并利用 MVCC 来获取一个一致性的数据库快照进行备份,而不需要锁表。

局限性

  1. 额外的存储空间:MVCC 需要维护多个数据版本,Undo Log 会占用大量磁盘空间。

  2. 额外的维护成本:需要定期清理不再需要的旧版本数据(Purge 操作),否则会导致 Undo Log 膨胀。

  3. 无法完全摆脱锁:MVCC 通常与“next-key lock”配合使用来解决幻读。对于诸如 SELECT ... FOR UPDATEUPDATEDELETE 等当前读操作,仍然需要加锁来确保数据安全


总结

MVCC 是 MySQL InnoDB 实现高性能并发控制的基石。它通过巧妙的“数据多版本”和“一致性读视图”机制,完美地平衡了并发性能数据一致性之间的矛盾。理解 MVCC,不仅有助于我们更好地设计数据库表结构和编写 SQL,也能在遇到并发问题时,快速定位其根源。

下次当你享受 MySQL 的高并发查询性能时,别忘了背后这位默默工作的“数据时光机”——MVCC。

http://www.dtcms.com/a/395020.html

相关文章:

  • 汽车冷却系统的冷却水管介绍
  • 基础架构设计
  • 从分散到统一:基于Vue3的地图模块重构之路
  • JVM实际内存占用
  • Spark SQL 桶抽样(Bucket Sampling)
  • 常见的【垃圾收集算法】
  • 如何解决 pip install 安装报错 ModuleNotFoundError: No module named ‘django’ 问题
  • jvm之【垃圾回收器】
  • Tomcat基础知识
  • Will、NGC游戏模拟器 Dolphin海豚模拟器2509最新版 电脑+安卓版 附游戏
  • ELK企业级日志分析系统详解:从入门到部署实践
  • 2025年Spring Security OAuth2实现github授权码模式登录
  • Kafka面试精讲 Day 22:Kafka Streams流处理
  • ELK大总结20250922
  • 基于Hadoop生态的汽车全生命周期数据分析与可视化平台-基于Python+Vue的二手车智能估价与市场分析系统
  • 基于TV模型利用Bregman分裂算法迭代对图像进行滤波和复原处理
  • 利用 Perfmon.exe 与 UMDH 组合分析 Windows 程序内存消耗
  • hello算法笔记 02
  • 二级域名解析与配置
  • 如何学习国库会计知识
  • 【读论文】压缩双梳光谱技术
  • Spark Structured Streaming端到端延迟优化实践指南
  • 【.NET实现输入法切换的多种方法解析】,第566篇
  • 性能测试-jmeter13-性能资源指标监控
  • 基于华为openEuler系统安装PDF查看器PdfDing
  • PyTorch 神经网络工具箱核心知识梳理
  • 【LangChain指南】Agents
  • Linux 的进程信号与中断的关系
  • IS-IS 协议中,是否在每个 L1/L2 设备上开启路由渗透
  • pycharm常用功能及快捷键