【MySQL】MVCC工作原理、事务隔离机制、undo log回滚日志、间隙锁
一、什么是MVCC?
MVCC,即 Multiversion Concurrency Control(多版本并发控制),它是数据库实现并发控制的一种方式。
MVCC 的核心思想是:
为每个事务提供数据的“快照”版本,从而避免加锁,提高读操作的并发性。
作用:
- 允许 读操作(SELECT)不用加锁,从而避免阻塞。
- 避免“读写冲突”,提高并发性能。
- 实现事务的 隔离性(特别是实现 REPEATABLE READ、READ COMMITTED)
💡 二、MVCC 是如何工作的(以 InnoDB 为例)
InnoDB 如何实现 MVCC?
它通过以下两个隐藏字段实现版本控制:
trx_id:每行记录最后一次修改它的事务ID。roll_pointer:指向旧版本(undo log)的指针,形成多版本链。
此外,事务开始时有一个 read view(快照视图),用来判断哪些版本是“可见的”。
举个例子:
- 假设 A 开始一个事务,读取一行数据。
- 此时 B 事务修改了该行数据,并提交。
- A 仍然能看到旧版本的数据(通过 undo log 追溯),这是快照隔离。
👉 这种读取叫做 一致性读(Consistent Read),完全不加锁!
📌 四、MyISAM 为什么不支持 MVCC?
MyISAM 不支持事务,因此也就不支持:
- undo log
- 多版本
- read view 快照
当有一个查询时,它只能使用表级锁来保证一致性。这种方式:
- 并发性能低(特别是写多的时候)
- 无法提供事务隔离级别(没有REPEATABLE READ等)
🧠 总结:
MySQL 存储引擎 MVCC 差异总结
- InnoDB:支持事务 + 行级锁 + MVCC(多版本并发控制)
-> 读不加锁,性能好,支持一致性读 - MyISAM:不支持事务,不支持 MVCC,使用表级锁
-> 读写容易阻塞,性能差,读的是最新数据
🧱 一、前置知识:事务隔离级别(SQL标准)
事务隔离级别从低到高:
| 隔离级别 | 描述 | 常见问题 |
|---|---|---|
| READ UNCOMMITTED | 可以读到未提交的数据 | 脏读(读未提交的数据) |
| READ COMMITTED | 只能读到已提交的数据 | 不可重复读 |
| REPEATABLE READ | 多次读取同一数据结果一致 | 幻读 |
| SERIALIZABLE | 全部加锁,串行执行 | 性能差但最安全 |
🔍 二、MVCC 如何支持隔离性?
✅ REPEATABLE READ(可重复读,MySQL 默认)
多次
SELECT相同数据时,读到的是事务开始时的数据快照(read view),不受其他事务影响。
✔ 具体实现:
- 事务一开始,InnoDB 创建一个 read view。
- 所有
SELECT查询都是基于这个 read view。 - 即使别的事务修改并提交了数据,本事务看到的还是原来的版本(通过 undo log 回溯)。
- 会出现
幻读,即读取到的不是最新数据,因为可重复读采用的是undo log的read view快照机制,用的是事务开始保存的快照,而不是实时数据。
🧠 举个例子:
-- 事务 A
START TRANSACTION;
SELECT * FROM user WHERE id=1; -- 假设 name='Tom'-- 事务 B
START TRANSACTION;
UPDATE user SET name='Jerry' WHERE id=1;
COMMIT;-- 回到事务 A
SELECT * FROM user WHERE id=1; -- name 仍然是 'Tom',实现了 repeatable read
事务 A 的所有读取都基于它开始时的快照,看到的是“旧世界”。
✅ READ COMMITTED(已提交读)
每次
SELECT都读取当前最新提交版本的数据。
✔ 具体实现:
- 每次读取都会生成一个新的undo log的 read view。
- 所以可以读到别的事务已提交的新数据。
- 可能出现
不可重复读,即,同一事务中select的是不同数据。
🧠 举个例子:
-- 事务 A
START TRANSACTION;
SELECT * FROM user WHERE id=1; -- name = 'Tom'-- 事务 B
START TRANSACTION;
UPDATE user SET name='Jerry' WHERE id=1;
COMMIT;-- 回到事务 A
SELECT * FROM user WHERE id=1; -- name = 'Jerry'(读到了新数据)
这种机制虽然不会脏读,但不能重复读,因为两次查询结果不一样。
🧠 总结:
InnoDB 实现事务隔离性核心在于:MVCC + undo log + read view
REPEATABLE READ:
- 每个事务在开始时创建 read view
- 所有查询基于这个快照版本
- 即使其他事务提交了修改,也读不到(实现“可重复读”)
READ COMMITTED:
- 每次查询时都重新生成 read view
- 总是读取最新提交的数据
- 能避免脏读,但可能“不可重复读”
MySQL 默认使用 REPEATABLE READ,避免幻读靠间隙锁(gap lock)
📦 一、四种事务隔离级别及存在的问题汇总
| 隔离级别 | 是否可读未提交 | 是否可重复读 | 是否会幻读 | 使用场景(读一致性) |
|---|---|---|---|---|
| READ UNCOMMITTED | ✅ 是 | ❌ 否 | ✅ 是 | 最低一致性,无任何保障 |
| READ COMMITTED | ❌ 否(读提交) | ❌ 否 | ✅ 是 | 大多数数据库默认,如Oracle |
| REPEATABLE READ | ❌ 否 | ✅ 是 | ❌(InnoDB中) | MySQL默认,支持一致快照 |
| SERIALIZABLE | ❌ 否 | ✅ 是 | ✅ 否(加锁) | 串行执行,开销大 |
🔍 每种隔离级别的问题示例
| 问题类型 | 描述 | 发生条件 |
|---|---|---|
| 脏读(Dirty Read) | 读到了未提交的数据 | 仅在 READ UNCOMMITTED 下可能发生 |
| 不可重复读(Non-repeatable Read) | 同一条记录两次读结果不一致 | READ COMMITTED |
| 幻读(Phantom Read) | 两次读取结果行数不一致(新增/删除) | REPEATABLE READ 但有范围查询时才会发生 |
🧬 二、MVCC 实现关键机制:undo log + read view
✅ undo log(回滚日志)
- 记录旧版本数据,用于:
- 回滚(ROLLBACK)
- 一致性读(Consistent Read)
undo log 的基本结构
每条记录维护:
- 修改前的值(旧版本)
- 事务 ID(trx_id)
- 回滚指针(roll_pointer)指向上一个版本
✅ read view(快照视图)
- 事务在 第一次执行一致性读(SELECT)时创建
- 用于判断某条数据的哪个版本“对当前事务可见”
判断规则(InnoDB MVCC 可见性判断):
当前事务ID = T
记录版本的 trx_id = R如果 R < 最小活跃事务ID:可见(已经提交)
如果 R == 当前事务ID:可见(自己改的)
如果 R 是活跃事务ID之一:不可见(别人还没提交)
🧱 三、幻读的由来与间隙锁的解决方案
🧨 什么是幻读(Phantom Read)?
指一类特殊的不可重复读 —— 两次范围查询返回不同数量的结果。
示例:
-- 事务 A
START TRANSACTION;
SELECT * FROM user WHERE age > 20;-- 事务 B
INSERT INTO user (name, age) VALUES ('NewUser', 21);
COMMIT;-- 回到事务 A
SELECT * FROM user WHERE age > 20; -- 发现多了一条,产生幻读
🧰 InnoDB 的解决方法:间隙锁(Gap Lock)
在可重复读隔离级别下,为防止幻读,InnoDB 对范围查询加“间隙锁”。
间隙锁含义:
- 不锁定具体记录,而锁定“两个记录之间的间隙”。
- 其他事务不能在这个间隙中插入新数据。
举例:
SELECT * FROM user WHERE age > 20 FOR UPDATE;
-- 会锁住 20 ~ ∞ 之间的“空隙”,禁止插入
⚠ 注意:
- 间隙锁只在 REPEATABLE READ + 索引条件范围查询 + FOR UPDATE 或隐式锁定下生效
- 不使用
FOR UPDATE时,一般是一致性读,只靠 undo log,不加锁
🧠 总结:
事务隔离级别问题对比
- READ UNCOMMITTED: 有脏读,不推荐使用
- READ COMMITTED: 无脏读,有不可重复读,Oracle默认
- REPEATABLE READ: 无脏读、可重复读、InnoDB用间隙锁避免幻读(MySQL默认)
- SERIALIZABLE: 全部加锁,开销大,极少使用
InnoDB 实现关键:MVCC
- undo log:记录旧版本数据
- read view:事务可见性判断依据
- 间隙锁:锁定范围,阻止幻读(只在RR可重复读下有效)
https://github.com/0voice
相关文章:
【MySQL】MVCC工作原理、事务隔离机制、undo log回滚日志、间隙锁
一、什么是MVCC? MVCC,即 Multiversion Concurrency Control(多版本并发控制),它是数据库实现并发控制的一种方式。 MVCC 的核心思想是: 为每个事务提供数据的“快照”版本,从而避免加锁&…...
无人机气动-结构耦合技术要点与难点
一、技术要点 1. 多学科耦合建模 气动载荷与结构响应的双向耦合:气动力(如升力、阻力、力矩)导致结构变形,而变形改变气动外形,进一步影响气流分布,形成闭环反馈。 建模方法: 高精度C…...
七大数据库全面对比:ClickHouse、ES、MySQL等特性、优缺点及使用场景
七大数据库全面对比:ClickHouse、ES、MySQL等特性、优缺点及使用场景 引言 在数字化时代,数据库的选择对于业务的成功至关重要。本文将通过表格形式,对ClickHouse、Elasticsearch(ES)、MySQL、SQL Server、MongoDB、HBase、Cassandra这七大数据库进行特性、优缺点及使用…...
element-ui plus 中 filter-method 函数多次触发问题解决
前情提要 点进这个文章的小伙伴,应该都是为了解决一个需求,把原本的前端过滤改为后端过滤,但是将filter-method修改为后端取数据后,发现其触发了很多次。博主也是在修改表格过滤时用到了这个坑,本篇文章为大家解决一下…...
基于【Lang Chain】构建智能问答系统的实战指南
🐇明明跟你说过:个人主页 🏅个人专栏:《深度探秘:AI界的007》 🏅 🔖行路有良友,便是天堂🔖 目录 一、引言 1、什么是Lang Chain 2、LangChain在问答系统中的核心优…...
idea的快捷键使用以及相关设置
文章目录 快捷键常用设置 快捷键 快捷键作用ctrlshift/注释选中内容Ctrl /注释一行/** Enter文档注释ALT SHIFT ↑, ALT SHIFT ↓上下移动当前代码Ctrl ALT L格式化代码Ctrl X删除所在行并复制该行Ctrl D复制当前行数据到下一行main/psvm快速生成入口程序soutSystem.o…...
TestHubo安装及入门指南
TestHubo是一款开源免费的测试管理工具,提供一站式测试解决方案,涵盖功能测试、接口测试、性能测试以及 Web 和 App 测试等多个维度。TestHubo 整合了全面的测试能力,使团队可以在一个平台内完成所有测试需求。本文将介绍如何快速安装配置及入…...
react tailwindcss最简单的开始
参考教程: Install Tailwind CSS with Vite - TailwindCSS中文文档 | TailwindCSS中文网https://www.tailwindcss.cn/docs/guides/vite操作过程: Microsoft Windows [版本 10.0.26100.3476] (c) Microsoft Corporation。保留所有权利。D:\gitee\tailwi…...
openGauss新特性 | 自动参数化执行计划缓存
目录 自动化参数执行计划缓存简介 SQL参数化及约束条件 一般常量参数化示例 总结 自动化参数执行计划缓存简介 执行计划缓存用于减少执行计划的生成次数。openGauss数据库会缓存之前生成的执行计划,以便在下次执行该SQL时直接使用,可…...
3、组件:魔法傀儡的诞生——React 19 组件化开发全解析
一、开篇:魔法傀儡的觉醒 "每个React组件都像一具魔法傀儡,"邓布利多校长挥动魔杖,空中浮现出闪烁的代码字符,"它们能自主思考、协同工作,甚至能跨越时空(服务器与客户端)执行任…...
使用Python实现矢量路径的压缩、解压与可视化
引言 在图形设计和Web开发中,矢量路径数据的高效存储与传输至关重要。本文将通过一个Python示例,展示如何将复杂的矢量路径命令序列压缩为JSON格式,再将其解压还原,并通过matplotlib进行可视化。这一过程可应用于字体设计、矢量图…...
达梦数据库迁移问题总结
更多技术博客,请关注微信公众号:运维之美 问题一、DTS工具运行乱码 开启图形化 [rootlocalhost ~]# xhost #如果命令不存在执行sudo yum install xorg-x11-server-utils xhost: unable to open display "" [rootlocalhost ~]# su - dmd…...
OpenHarmony荷兰研习会回顾 | 仓颉语言赋能原生应用开发实践
近日,由全球顶级学术峰会EuroSys/ASPLOS和OpenHarmony社区在荷兰鹿特丹合办的操作系统深度研习会圆满收官,本次研习会以"架构探秘-开发实践-创新实验"三位一体的进阶模式,为全球开发者构建了沉浸式技术探索平台。其中,由…...
【远程工具】0 std::process::Command 介绍
std::process::Command 是 Rust 标准库中用于创建和配置子进程的主要类型。它允许你启动新的进程、设置其参数和环境变量、重定向输入/输出等。 基本用法 use std::process::Command;let output Command::new("echo").arg("Hello, world!").output().ex…...
【JAVA】JVM 堆内存“缓冲空间”的压缩机制及调整方法
1. 缓冲空间是否可压缩? 是的,JVM 会在满足条件时自动收缩堆内存,将未使用的缓冲空间释放回操作系统。但需满足以下条件: GC 触发堆收缩:某些垃圾回收器(如 G1、Serial、Parallel)在 Full GC …...
RV1126 人脸识别门禁系统解决方案
1. 方案简介 本方案为类人脸门禁机的产品级解决方案,已为用户构建一个带调度框架的UI应用工程;准备好我司的easyeai-api链接调用;准备好UI的开发环境。具备低模块耦合度的特点。其目的在于方便用户快速拓展自定义的业务功能模块,以及快速更换UI皮肤。 2. 快速上手 2.1 开…...
matlab内置的git软件版本管理功能
1、matlab多人协作开发比普通的嵌入式软件开发困难很多 用过matlab的人都知道,版本管理对于matlab来说真的很费劲,今天介绍的这个工具也不是说它就解决了这个痛点,只是让它变得简单一点。版本管理肯定是不可或缺的,干就完了 2、操作说明 如图所示,源代码管理,选项罗列的…...
【问题排查】SQLite安装失败
启动 Django 自带的开发服务器 python manage.py runserver出现如下报错: [rootiZ2zedudtf2cwzi9argky2Z myproject]# python manage.py runserver Watching for file changes with StatReloader Performing system checks...System check identified no issues (…...
Express中间件(Middleware)详解:从零开始掌握(2)
1. 请求耗时中间件的增强版 问题:原版只能记录到控制台,如何记录到文件? 改进点: 使用process.hrtime()是什么?获取更高精度的时间支持将日志写入文件记录更多信息(IP地址、状态码)工厂函数模式使中间件可配置 con…...
《前端面试题之 CSS篇(第一集)》
目录 1、CSS的盒模型2、CSS选择器及其优先级3、隐藏元素的方法有那些4、px、em、rem的区别及使用场景5、重排、重绘有什么区别6、水平垂直居中的实现7、CSS中可继承与不可继承属性有哪些8、Sass、Less 是什么?为什么要使用他们?9、CSS预处理器/后处理器是…...
MySQL部分总结
mysql学习笔记,如有不足还请指出,谢谢。 外连接,内连接,全连接 外连接:左外、右外 内连接:自己和自己连接 全连接:左外连接右外链接 mysql unique字段 unique可以在数据库层面避免插入相同…...
2025第十六届蓝桥杯PythonB组部分题解
一、攻击次数 题目描述 小蓝操控三个英雄攻击敌人,敌人初始血量2025: 第一个英雄每回合固定攻击5点第二个英雄奇数回合攻击15点,偶数回合攻击2点第三个英雄根据回合数除以3的余数攻击:余1攻2点,余2攻10点࿰…...
RocketMQ 中的 MessageStore 组件:消息存储的核心枢纽
引言 在现代分布式系统中,消息队列扮演着至关重要的角色,它能够实现系统间的异步通信、解耦服务以及削峰填谷等功能。RocketMQ 作为一款高性能、高可靠的分布式消息队列,在众多企业级应用中得到了广泛的应用。而在 RocketMQ 的架构体系里&am…...
Linux Kernel 2
地址空间(Address Space) 一、物理地址空间(Physical Address Space) 物理地址空间 是指 RAM 和设备内存 在系统内存总线上所呈现的地址布局。 举例:在典型的 32 32 32 位 Intel 架构中, RAM(…...
AndroidTV D贝桌面-v3.2.5-[支持文件传输]
AndroidTV D贝桌面 链接:https://pan.xunlei.com/s/VONXSBtgn8S_BsZxzjH_mHlAA1?pwdzet2# AndroidTV D贝桌面-v3.2.5[支持文件传输] 第一次使用的话,壁纸默认去掉的,不需要按遥控器上键,自己更换壁纸即可...
线性方程组的解法
文章目录 线性方程组的解法认识一些基本的矩阵函数MATLAB 实现机电工程学院教学函数构造1.高斯消元法2.列主元消去法3. L U LU LU分解法 线性方程组的解法 看到以下线性方程组的一般形式:设有以下的 n n n阶线性方程组: A x b \mathbf{Ax}\mathbf{b} A…...
轻量级锁是什么?轻在哪里?重量级锁是什么?重在哪里?
轻量级锁 vs 重量级锁:核心区别与设计哲学 在JVM的锁优化体系中,轻量级锁和重量级锁是两种不同竞争强度下的解决方案。它们的核心差异体现在 资源消耗、适用场景和实现机制 上。以下是详细对比: 一、轻量级锁(Thin Lockÿ…...
Python赋能量子计算:算法创新与应用拓展
量子计算与Python结合的算法开发与应用研究 摘要 量子计算作为计算机科学的前沿技术,凭借其独特的计算能力在解决复杂问题方面展现出巨大潜力。Python作为一种高效、灵活的编程语言,为量子计算算法的开发提供了强大的支持。本文从研究学者的视角,系统探讨了量子计算与Pytho…...
Java学习笔记(多线程):ReentrantLock 源码分析
本文是自己的学习笔记,主要参考资料如下 JavaSE文档 1、AQS 概述1.1、锁的原理1.2、任务队列1.2.1、结点的状态变化 1.3、加锁和解锁的简单流程 2、ReentrantLock2.1、加锁源码分析2.1.1、tryAcquire()的具体实现2.1.2、acquirQueued()的具体实现2.1.3、tryLock的具…...
【LeetCode 热题100】二叉树构造题精讲:前序 + 中序建树 有序数组构造 BST(力扣105 / 108)(Go语言版)
🌱 二叉树构造题精讲:前序 中序建树 & 有序数组构造 BST 本文围绕二叉树的两类构造类题目展开解析: 从前序与中序遍历序列构造二叉树 将有序数组转换为二叉搜索树 我们将从「已知遍历构造树」和「平衡构造 BST」两个角度,拆…...
