MySQL MVCC 机制详解

news2025/4/15 13:32:38

MySQL MVCC 机制详解

1. MVCC 基本概念

MVCC 是一种并发控制的方法,主要用于数据库管理系统,允许多个事务同时读取数据库中的同一个数据项,而不需要加锁,从而提高了数据库的并发性能。

┌─────────────────────────────────────┐
│         MVCC 的核心思想              │
│                                     │
│  对数据进行修改操作时,不会直接覆盖数据,│
│  而是创建一个新版本,让读操作可以看到   │
│  修改前的数据                        │
└─────────────────────────────────────┘

2. MVCC 在 InnoDB 中的实现

InnoDB 引擎下 MVCC 的实现主要基于以下几个关键概念:

2.1 隐藏字段

InnoDB 为每一行记录添加了三个隐藏字段:

┌───────────────────────────────────────────────────────┐
│                   InnoDB 行记录结构                     │
├───────────┬───────────┬───────────┬───────────────────┤
│ DB_TRX_ID │ DB_ROLL_PTR│ DB_ROW_ID │ 实际数据列(可见部分) │
│ 事务ID    │ 回滚指针   │ 行ID(可选) │                    │
└───────────┴───────────┴───────────┴───────────────────┘
  • DB_TRX_ID:创建或最后修改该记录的事务ID
  • DB_ROLL_PTR:指向 undo log 的指针,用于数据回滚
  • DB_ROW_ID:如果没有主键,InnoDB 会自动生成的行ID

2.2 undo log 版本链

当一行记录被修改时,InnoDB 会将旧版本的记录写入 undo log,并在当前记录中通过回滚指针指向这个 undo log 记录,形成一个版本链。

┌──────────────────────────────────────────────────────────────┐
│                       版本链示意图                            │
│                                                              │
│  最新记录                                                     │
│  ┌─────────┬─────────┬─────────┬───────────┐                 │
│  │TRX_ID=30│ROLL_PTR │ROW_ID   │name="张三" │                 │
│  └─────────┴─────────┴─────────┴───────────┘                 │
│      │                                                       │
│      ▼ 回滚指针指向                                           │
│  Undo Log 1                                                  │
│  ┌─────────┬─────────┬─────────┬───────────┐                 │
│  │TRX_ID=20│ROLL_PTR │ROW_ID   │name="李四" │                 │
│  └─────────┴─────────┴─────────┴───────────┘                 │
│      │                                                       │
│      ▼ 回滚指针指向                                           │
│  Undo Log 2                                                  │
│  ┌─────────┬─────────┬─────────┬───────────┐                 │
│  │TRX_ID=10│ROLL_PTR │ROW_ID   │name="王五" │                 │
│  └─────────┴─────────┴─────────┴───────────┘                 │
│                                                              │
└──────────────────────────────────────────────────────────────┘

2.3 ReadView

ReadView 是 MVCC 实现的关键机制,它决定了当前事务能够看到哪个版本的数据。ReadView 包含以下重要信息:

  • m_ids:当前系统中活跃的事务ID集合
  • min_trx_id:活跃的最小事务ID
  • max_trx_id:系统中将要分配给下一个事务的ID
  • creator_trx_id:创建该 ReadView 的事务ID
┌──────────────────────────────────────────────┐
│               ReadView 示意图                 │
│                                              │
│  ┌────────────────────────────────────────┐  │
│  │ m_ids: [10, 20, 30]                    │  │
│  │ min_trx_id: 10                         │  │
│  │ max_trx_id: 40                         │  │
│  │ creator_trx_id: 25                     │  │
│  └────────────────────────────────────────┘  │
│                                              │
└──────────────────────────────────────────────┘

3. MVCC 可见性判断规则

当一个事务要读取一行记录时,它会根据 ReadView 和记录的 DB_TRX_ID 来判断该版本的记录是否可见:

┌─────────────────────────────────────────────────────────────────┐
│                  MVCC 可见性判断流程图                           │
│                                                                 │
│   ┌───────────────┐                                             │
│   │ 开始判断可见性 │                                             │
│   └───────┬───────┘                                             │
│           ▼                                                     │
│   ┌───────────────────────────────┐     是     ┌───────────┐     │
│   │ trx_id == creator_trx_id?    ├────────────►│ 可见     │     │
│   └───────────┬───────────────────┘            └───────────┘     │
│               │ 否                                               │
│               ▼                                                 │
│   ┌───────────────────────────────┐     是     ┌───────────┐     │
│   │ trx_id < min_trx_id?         ├────────────►│ 可见     │     │
│   └───────────┬───────────────────┘            └───────────┘     │
│               │ 否                                               │
│               ▼                                                 │
│   ┌───────────────────────────────┐     是     ┌───────────┐     │
│   │ trx_id >= max_trx_id?        ├────────────►│ 不可见   │     │
│   └───────────┬───────────────────┘            └───────────┘     │
│               │ 否                                               │
│               ▼                                                 │
│   ┌───────────────────────────────┐     是     ┌───────────┐     │
│   │ trx_id 在 m_ids 中?           ├────────────►│ 不可见   │     │
│   └───────────┬───────────────────┘            └───────────┘     │
│               │ 否                                               │
│               ▼                                                 │
│               ┌───────────┐                                     │
│               │ 可见      │                                     │
│               └───────────┘                                     │
└─────────────────────────────────────────────────────────────────┘

4. 不同隔离级别下的 MVCC 行为

MVCC 主要在 READ COMMITTED 和 REPEATABLE READ 隔离级别下工作:

┌─────────────────────────────────────────────────────────────────┐
│               不同隔离级别的 ReadView 创建时机                    │
│                                                                 │
│  ┌────────────────────┐        ┌─────────────────────────────┐  │
│  │    READ COMMITTED  │        │      REPEATABLE READ       │  │
│  ├────────────────────┤        ├─────────────────────────────┤  │
│  │                    │        │                             │  │
│  │ 每次SELECT时创建新的 │        │ 事务开始时创建一次ReadView   │  │
│  │ ReadView           │        │ 之后所有查询复用这个ReadView │  │
│  │                    │        │                             │  │
│  └────────────────────┘        └─────────────────────────────┘  │
│                                                                 │
└─────────────────────────────────────────────────────────────────┘

4.1 READ COMMITTED

  • 每次SELECT都会创建一个新的ReadView
  • 可以看到其他已提交事务的更改
  • 解决了脏读问题,但可能出现不可重复读

4.2 REPEATABLE READ(MySQL默认)

  • 在事务开始时创建一个ReadView,之后的查询都复用这个ReadView
  • 在整个事务过程中,对已经读取的数据,其他事务的更新对当前事务不可见
  • 解决了不可重复读问题

5. MVCC的实际例子

假设我们有一个简单的表格和以下操作序列:

创建表: CREATE TABLE user(id INT PRIMARY KEY, name VARCHAR(20));
初始数据: INSERT INTO user VALUES(1, '小明');

接下来,有三个事务同时操作这条记录:

┌─────────────────────────────────────────────────────────────────┐
│                       事务并发执行示例                            │
│                                                                 │
│  时间 │ 事务A(trx_id=10)  │ 事务B(trx_id=20)  │ 事务C(trx_id=30)  │
│ ─────┼──────────────────┼──────────────────┼────────────────── │
│  t1  │ BEGIN;           │                  │                   │
│  t2  │                  │ BEGIN;           │                   │
│  t3  │                  │                  │ BEGIN;            │
│  t4  │ SELECT * FROM    │                  │                   │
│      │ user WHERE id=1; │                  │                   │
│      │ 结果: '小明'      │                  │                   │
│  t5  │                  │ UPDATE user SET  │                   │
│      │                  │ name='小红'       │                   │
│      │                  │ WHERE id=1;      │                   │
│  t6  │                  │ COMMIT;          │                   │
│  t7  │ SELECT * FROM    │                  │                   │
│      │ user WHERE id=1; │                  │                   │
│      │ 结果(RC): '小红'  │                  │                   │
│      │ 结果(RR): '小明'  │                  │                   │
│  t8  │                  │                  │ UPDATE user SET   │
│      │                  │                  │ name='小黑'        │
│      │                  │                  │ WHERE id=1;       │
│  t9  │                  │                  │ COMMIT;           │
│ t10  │ SELECT * FROM    │                  │                   │
│      │ user WHERE id=1; │                  │                   │
│      │ 结果(RC): '小黑'  │                  │                   │
│      │ 结果(RR): '小明'  │                  │                   │
│ t11  │ COMMIT;          │                  │                   │
└─────────────────────────────────────────────────────────────────┘

版本链变化过程:

初始状态:
┌─────────┬─────────┬─────────┬───────────┐
│TRX_ID=1 │ROLL_PTR │ROW_ID   │name="小明" │
└─────────┴─────────┴─────────┴───────────┘

事务B更新后:
┌─────────┬─────────┬─────────┬───────────┐
│TRX_ID=20│ROLL_PTR │ROW_ID   │name="小红" │
└─────────┴─────────┴─────────┴───────────┘
    │
    ▼
┌─────────┬─────────┬─────────┬───────────┐
│TRX_ID=1 │ROLL_PTR │ROW_ID   │name="小明" │
└─────────┴─────────┴─────────┴───────────┘

事务C更新后:
┌─────────┬─────────┬─────────┬───────────┐
│TRX_ID=30│ROLL_PTR │ROW_ID   │name="小黑" │
└─────────┴─────────┴─────────┴───────────┘
    │
    ▼
┌─────────┬─────────┬─────────┬───────────┐
│TRX_ID=20│ROLL_PTR │ROW_ID   │name="小红" │
└─────────┴─────────┴─────────┴───────────┘
    │
    ▼
┌─────────┬─────────┬─────────┬───────────┐
│TRX_ID=1 │ROLL_PTR │ROW_ID   │name="小明" │
└─────────┴─────────┴─────────┴───────────┘

6. MVCC的优缺点

优点:

  • 提高并发性能,读不阻塞写,写不阻塞读
  • 解决了读-写冲突问题
  • 支持事务的隔离级别实现

缺点:

  • 需要额外的存储空间维护旧版本数据
  • 需要定期清理过时的旧版本数据
  • 实现较为复杂

总结

MVCC 是 MySQL InnoDB 存储引擎中实现高并发的关键技术,通过在每行记录后面保存两个隐藏的列(事务ID和回滚指针)来实现的。它能够让不同事务的读、写操作并发执行,同时保证事务的隔离性。根据不同的隔离级别,MySQL 会采用不同的策略来创建和维护 ReadView,从而影响数据的可见性。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2334203.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

0.机器学习基础

0.人工智能概述&#xff1a; &#xff08;1&#xff09;必备三要素&#xff1a; 数据算法计算力 CPU、GPU、TPUGPU和CPU对比&#xff1a; GPU主要适合计算密集型任务&#xff1b;CPU主要适合I/O密集型任务&#xff1b; 【笔试问题】什么类型程序适合在GPU上运行&#xff1…

系统与网络安全------网络通信原理(4)

资料整理于网络资料、书本资料、AI&#xff0c;仅供个人学习参考。 网络层解析 IP 网络层概述 位于OSI模型第三层作用 定义网络设备的逻辑地址&#xff0c;俗称网络层地址&#xff08;如IP地址&#xff09; 在不同的网段之间选择最佳数据转发路径 协议 IP协议 IP数据包…

Java基础 4.12

1.方法的重载&#xff08;OverLoad&#xff09; 基本介绍 Java中允许同一个类&#xff0c;多个同名方法的存在&#xff0c;但要求形参列表不一致&#xff01; 如 System.out.println(); out是PrintStream类型 重载的好处 减轻了起名的麻烦减轻了记名的麻烦 2.重载的快速入…

XILINX DDR3专题---(1)IP核时钟框架介绍

1.什么是Reference Clock&#xff0c;这个时钟一定是200MHz吗&#xff1f; 2.为什么APP_DATA是128bit&#xff0c;怎么算出来的&#xff1f; 3.APP &#xff1a;MEM的比值一定是1:4吗&#xff1f; 4.NO BUFFER是什么意思&#xff1f; 5.什么情况下Reference Clock的时钟源可…

clickhouse注入手法总结

clickhouse 遇到一题clickhouse注入相关的&#xff0c;没有见过&#xff0c;于是来学习clickhouse的使用&#xff0c;并总结相关注入手法。 环境搭建 直接在docker运行 docker pull clickhouse/clickhouse-server docker run -d --name some-clickhouse-server --ulimit n…

React 组件样式

在这里插入图片描述 分为行内和css文件控制 行内 通过CSS中类名文件控制

利用 pyecharts 实现地图的数据可视化——第七次人口普查数据的2d、3d展示(关键词:2d 、3d 、map、 geo、涟漪点)

参考文档&#xff1a;链接: link_pyecharts 官方文档 1、map() 传入省份全称&#xff0c;date_pair 是列表套列表 [ [ ],[ ] … ] 2、geo() 传入省份简称&#xff0c;date_pair 是列表套元组 [ ( ),( ) … ] 1、准备数据 population_data&#xff1a;简称经纬度 population_da…

解决 Elasticsearch 分页查询性能瓶颈——从10分钟到秒级的优化实践

大家好&#xff0c;我是铭毅天下&#xff0c;一名专注于 Elasticsearch &#xff08;以下简称ES&#xff09;技术栈的技术爱好者。 今天我们来聊聊球友提出的一个实际问题&#xff1a; ES分页查询性能很差&#xff0c;使用from/size方式检索居然需要10分钟&#xff01; 这是一个…

记录IBM服务器检测到备份GPT损坏警告排查解决过程

服务器设备&#xff1a;IBM x3550 M4 Server IMM默认IP地址&#xff1a;192.168.70.125 用户名&#xff1a;USERID 密码&#xff1a;PASSW0RD&#xff08;注意是零0&#xff09; 操作系统&#xff1a;Windows Hyper-V Server 2016 IMM Web System Status Warning&#xff1…

毫米波测试套装速递!高效赋能5G/6G、新材料及智能超表面(RIS)研发

德思特&#xff08;Tesight&#xff09;作为全球领先的测试测量解决方案提供商&#xff0c;始终致力于为前沿技术研发提供高精度、高效率的测试工具。 针对毫米波技术在高频通信、智能超表面&#xff08;RIS&#xff09;、新材料等领域的快速应用需求&#xff0c;我们推出毫米…

Linux中卸载宝塔面板

输入命令 wget http://download.bt.cn/install/bt-uninstall.sh 执行脚本命令 sh bt-uninstall.sh 根据自己的情况选择1还是2 卸载完成校验 bt 这样我们的宝塔面板就卸载完了

无人机的振动与噪声控制技术!

一、振动控制技术要点 1. 振动源分析 气动振动&#xff1a;旋翼桨叶涡脱落&#xff08;如叶尖涡干涉&#xff09;、动态失速&#xff08;Dynamic Stall&#xff09;引发的周期性气动激振力&#xff08;频率与转速相关&#xff09;。 机械振动&#xff1a;电机偏心、传动轴不…

【蓝桥杯】第十六届蓝桥杯 JAVA B组记录

试题 A: 逃离高塔 很简单&#xff0c;签到题&#xff0c;但是需要注意精度&#xff0c;用int会有溢出风险 答案&#xff1a;202 package lanqiao.t1;import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.PrintWrit…

OSPF的接口网络类型【复习篇】

OSPF在不同网络环境下默认的不同工作方式 [a3]display ospf interface g 0/0/0 # 查看ospf接口的网络类型网络类型OSPF接口的网络类型&#xff08;工作方式&#xff09;计时器BMA&#xff08;以太网&#xff09;broadcast &#xff0c;需要DR/BDR的选举hello&#xff1a;10s…

python+requests接口自动化测试框架实例教程

&#x1f345; 点击文末小卡片 &#xff0c;免费获取软件测试全套资料&#xff0c;资料在手&#xff0c;涨薪更快 前段时间由于公司测试方向的转型&#xff0c;由原来的web页面功能测试转变成接口测试&#xff0c;之前大多都是手工进行&#xff0c;利用postman和jmeter进行…

2021第十二届蓝桥杯大赛软件赛省赛C/C++ 大学 B 组

记录刷题的过程、感悟、题解。 希望能帮到&#xff0c;那些与我一同前行的&#xff0c;来自远方的朋友&#x1f609; 大纲&#xff1a; 1、空间-&#xff08;题解&#xff09;-字节单位转换 2、卡片-&#xff08;题解&#xff09;-可以不用当组合来写&#xff0c;思维题 3、直…

智能资源管理机制-重传机制

一、发送端资源管理的核心机制 1. 滑动窗口&#xff08;Sliding Window&#xff09; 这是TCP协议的核心优化设计&#xff1a; 窗口动态滑动&#xff1a;发送端不需要保留所有已发送的分组&#xff0c;只需维护一个"发送窗口"窗口大小&#xff1a;由接收方通告的接…

设计模式 --- 原型模式

原型模式是创建型模式的一种&#xff0c;是在一个原型的基础上&#xff0c;建立一致的复制对象的方式。这个原型通常是我们在应用程序生命周期中需要创建多次的一个典型对象。为了避免初始化新对象潜在的性能开销&#xff0c;我们可以使用原型模式来建立一个非常类似于复印机的…

汽车软件开发常用的建模工具汇总

目录 往期推荐 1.Enterprise Architect&#xff08;EA&#xff09; 2.MATLAB/Simulink 3.TargetLink 4.Rational Rhapsody 5.AUTOSAR Builder 6.PREEvision 总结 往期推荐 2025汽车行业新宠&#xff1a;欧企都在用的工具软件ETAS工具链自动化实战指南&#xff1c;一&am…

SSM废品买卖回收管理系统的设计与实现

&#x1f345;点赞收藏关注 → 添加文档最下方联系方式咨询本源代码、数据库&#x1f345; 本人在Java毕业设计领域有多年的经验&#xff0c;陆续会更新更多优质的Java实战项目希望你能有所收获&#xff0c;少走一些弯路。&#x1f345;关注我不迷路&#x1f345; 项目视频 07…