MySQL MVCC 机制详解
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,从而影响数据的可见性。
相关文章:
MySQL MVCC 机制详解
MySQL MVCC 机制详解 1. MVCC 基本概念 MVCC 是一种并发控制的方法,主要用于数据库管理系统,允许多个事务同时读取数据库中的同一个数据项,而不需要加锁,从而提高了数据库的并发性能。 ┌──────────────────…...
【面试】封装、继承、多态的具象示例 模板编程的理解与应用场景 链表适用的场景
文章目录 C面试:封装、继承、多态的具象示例1. 封装 (Encapsulation)2. 继承 (Inheritance)3. 多态 (Polymorphism)综合示例:封装、继承、多态 C模板编程的理解与应用场景我对模板编程的理解C中最常用的模板编程场景1. STL (标准模板库)2. 通用容器实现3…...
0.机器学习基础
0.人工智能概述: (1)必备三要素: 数据算法计算力 CPU、GPU、TPUGPU和CPU对比: GPU主要适合计算密集型任务;CPU主要适合I/O密集型任务; 【笔试问题】什么类型程序适合在GPU上运行࿱…...
系统与网络安全------网络通信原理(4)
资料整理于网络资料、书本资料、AI,仅供个人学习参考。 网络层解析 IP 网络层概述 位于OSI模型第三层作用 定义网络设备的逻辑地址,俗称网络层地址(如IP地址) 在不同的网段之间选择最佳数据转发路径 协议 IP协议 IP数据包…...
Java基础 4.12
1.方法的重载(OverLoad) 基本介绍 Java中允许同一个类,多个同名方法的存在,但要求形参列表不一致! 如 System.out.println(); out是PrintStream类型 重载的好处 减轻了起名的麻烦减轻了记名的麻烦 2.重载的快速入…...
XILINX DDR3专题---(1)IP核时钟框架介绍
1.什么是Reference Clock,这个时钟一定是200MHz吗? 2.为什么APP_DATA是128bit,怎么算出来的? 3.APP :MEM的比值一定是1:4吗? 4.NO BUFFER是什么意思? 5.什么情况下Reference Clock的时钟源可…...
clickhouse注入手法总结
clickhouse 遇到一题clickhouse注入相关的,没有见过,于是来学习clickhouse的使用,并总结相关注入手法。 环境搭建 直接在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、涟漪点)
参考文档:链接: link_pyecharts 官方文档 1、map() 传入省份全称,date_pair 是列表套列表 [ [ ],[ ] … ] 2、geo() 传入省份简称,date_pair 是列表套元组 [ ( ),( ) … ] 1、准备数据 population_data:简称经纬度 population_da…...
解决 Elasticsearch 分页查询性能瓶颈——从10分钟到秒级的优化实践
大家好,我是铭毅天下,一名专注于 Elasticsearch (以下简称ES)技术栈的技术爱好者。 今天我们来聊聊球友提出的一个实际问题: ES分页查询性能很差,使用from/size方式检索居然需要10分钟! 这是一个…...
记录IBM服务器检测到备份GPT损坏警告排查解决过程
服务器设备:IBM x3550 M4 Server IMM默认IP地址:192.168.70.125 用户名:USERID 密码:PASSW0RD(注意是零0) 操作系统:Windows Hyper-V Server 2016 IMM Web System Status Warning࿱…...
毫米波测试套装速递!高效赋能5G/6G、新材料及智能超表面(RIS)研发
德思特(Tesight)作为全球领先的测试测量解决方案提供商,始终致力于为前沿技术研发提供高精度、高效率的测试工具。 针对毫米波技术在高频通信、智能超表面(RIS)、新材料等领域的快速应用需求,我们推出毫米…...
Linux中卸载宝塔面板
输入命令 wget http://download.bt.cn/install/bt-uninstall.sh 执行脚本命令 sh bt-uninstall.sh 根据自己的情况选择1还是2 卸载完成校验 bt 这样我们的宝塔面板就卸载完了...
无人机的振动与噪声控制技术!
一、振动控制技术要点 1. 振动源分析 气动振动:旋翼桨叶涡脱落(如叶尖涡干涉)、动态失速(Dynamic Stall)引发的周期性气动激振力(频率与转速相关)。 机械振动:电机偏心、传动轴不…...
Linux(CentOS10) gcc编译
本例子摘自《鸟哥的linux私房菜-基础学习第四版》 21.3 用make进行宏编译 书中的代码在本机器(版本见下)编译出错,改正代码后发布此文章: #kernel version: rootlocalhost:~/testmake# uname -a Linux localhost 6.12.0-65.el10.x86_64 #1…...
【蓝桥杯】第十六届蓝桥杯 JAVA B组记录
试题 A: 逃离高塔 很简单,签到题,但是需要注意精度,用int会有溢出风险 答案: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接口的网络类型(工作方式)计时器BMA(以太网)broadcast ,需要DR/BDR的选举hello:10s…...
微信小程序运行机制详解
微信小程序运行机制详解 微信小程序是介于 Web 和原生 App 之间的一种应用形态,具有无需安装、用完即走、体验流畅的特点。本文将从架构层面、运行环境、通信机制等方面深入剖析微信小程序的运行机制。 一、小程序运行架构概览 微信小程序采用双线程模型ÿ…...
python+requests接口自动化测试框架实例教程
🍅 点击文末小卡片 ,免费获取软件测试全套资料,资料在手,涨薪更快 前段时间由于公司测试方向的转型,由原来的web页面功能测试转变成接口测试,之前大多都是手工进行,利用postman和jmeter进行…...
2021第十二届蓝桥杯大赛软件赛省赛C/C++ 大学 B 组
记录刷题的过程、感悟、题解。 希望能帮到,那些与我一同前行的,来自远方的朋友😉 大纲: 1、空间-(题解)-字节单位转换 2、卡片-(题解)-可以不用当组合来写,思维题 3、直…...
spark课后总结
Spark运行架构 : 运行架构 Spark 采用master - slave(主从)结构。Driver 相当于master,负责管理集群中的作业任务调度;Executor 相当于slave,负责实际执行任务 核心组件 Driver:是Spark驱动…...
智能资源管理机制-重传机制
一、发送端资源管理的核心机制 1. 滑动窗口(Sliding Window) 这是TCP协议的核心优化设计: 窗口动态滑动:发送端不需要保留所有已发送的分组,只需维护一个"发送窗口"窗口大小:由接收方通告的接…...
设计模式 --- 原型模式
原型模式是创建型模式的一种,是在一个原型的基础上,建立一致的复制对象的方式。这个原型通常是我们在应用程序生命周期中需要创建多次的一个典型对象。为了避免初始化新对象潜在的性能开销,我们可以使用原型模式来建立一个非常类似于复印机的…...
基于SiamFC的红外目标跟踪
基于SiamFC的红外目标跟踪 1,背景与原理2,SiamFC跟踪方法概述2.1 核心思想2.2 算法优势3,基于SiamFC的红外跟踪代码详解3.1 网络定义与交叉相关模块3.2 SiamFC 跟踪器实现3.3 主程序:利用 OpenCV 实现视频跟踪4,总结与展望在红外监控、无人机防御以及低光照场景中,红外图…...
多模态学习分析(MLA)驱动高中差异化教学策略研究
一、引言 1.1 研究背景 在当今时代,教育数字化转型的浪潮正席卷全球,深刻地改变着教育的面貌。这一转型不仅是技术的革新,更是教育理念、教学模式和教育管理的全面变革。随着互联网、大数据、人工智能等现代信息技术在教育领域的广泛应用&a…...
设计模式 - 单例
单例设计模式 单例设计模式是一种创建型设计模式,它确保一个类只有一个实例,并提供一个全局访问点来获取这个实例。 在 JavaScript 里,有多种实现单例设计模式的方式,下面为你详细介绍: 1. 简单对象字面量实现 这是…...
汽车软件开发常用的建模工具汇总
目录 往期推荐 1.Enterprise Architect(EA) 2.MATLAB/Simulink 3.TargetLink 4.Rational Rhapsody 5.AUTOSAR Builder 6.PREEvision 总结 往期推荐 2025汽车行业新宠:欧企都在用的工具软件ETAS工具链自动化实战指南<一&am…...
SSM废品买卖回收管理系统的设计与实现
🍅点赞收藏关注 → 添加文档最下方联系方式咨询本源代码、数据库🍅 本人在Java毕业设计领域有多年的经验,陆续会更新更多优质的Java实战项目希望你能有所收获,少走一些弯路。🍅关注我不迷路🍅 项目视频 07…...
@SchedulerLock 防止分布式环境下定时任务并发执行
背景 在一个有多个服务实例的分布式系统中,如果你用 Scheduled 来定义定时任务,所有实例都会执行这个任务。ShedLock 的目标是只让一个实例在某一时刻执行这个定时任务。 使用步骤 引入依赖 当前以redisTemplate为例子,MongoDB、Zookeeper…...
实信号的傅里叶变换为何属于埃尔米特函数?从数学原理到 MATLAB 动态演示
引言 在信号处理领域,傅里叶变换是分析信号在频域表现的重要工具。特别是对于实信号,实信号是指在时间或空间域内取值为实数的信号,例如音频信号、温度变化等,它的傅里叶变换展现了一个非常特殊的数学性质——共轭对称性…...
