MySQL篇1——MySQL深度揭秘:事务隔离级别与 MVCC 原理详解

在数据库系统中,为了确保数据的正确性与一致性,引入了事务机制。一个事务代表着数据库执行的最小逻辑单元。


一、事务的四大特性(ACID)与实现原理

特性 描述 MySQL 依赖机制
原子性 Atomicity 事务中的操作要么全部执行成功,要么全部回滚 Undo Log(回滚日志)
一致性(目的) Consistency 事务前后数据需保持一致 依赖原子性+隔离性+持久性共同保证
隔离性 Isolation 并发事务之间互不影响 锁机制、MVCC
持久性 Durability 提交后的数据永久保存,即使系统宕机也不丢失 Redo Log(重做日志)

✔一致性是目的,其余三个是手段。


二、并发事务可能出现的问题

问题 含义 举例说明
脏读 Dirty Read 读取了其他事务未提交的数据 余额被读到未提交的修改
不可重复读 Non-repeatable Read 同一事务内两次读取同一行却得到不同结果 第二次读取时数据已被他人修改并提交
幻读 Phantom Read 同条查询条件返回的记录数不一致 第一次无结果 → 第二次新增了符合条件的数据

脏读问题展示:读到了脏数据,事务1修改了以后没提交就被事务2读了,这时候事务1回滚了。

不可重复读问题展示(一个事务中两次读取):事务1查询得到1000,这时候事务1还没结束,但是事务2修改了balance,事务1又读了一次发现是800。

幻读问题展示:事务1去汇总整个表的用户余额得到3000,这时候还没结束结束,事务二给一个用户加了1000余额,事务1又查了一次发现变成了4000。

幻读问题展示(场景2):当事务1去查询某个表发现没这个记录,他就想插入记录,但是插入的时候发现这个记录又存在了(就好像出现了幻觉),原因就是中途事务2刚好插入了这条数据。


三、事务隔离级别与解决效果

首先明白一点:隔离级别就是对应就是解决并发事务出现的问题。

名词理解:

读未提交:一个事务还没提交时,它做的变更就能被别的事务看到。

读已提交:一个事务提交之后,它做的变更才会被其他事务看到。

可重复读:在一个事务中前后两次重复读取同一条数据,数据内容一致。

串行化:通过加锁的方式让整个过程串行起来。对于同一行记录,"写"会加"写锁","读"会加"读锁"。当出现读写锁冲突的时候,后访问的事务必须等前一个事务执行完成,才能继续执行。

表格总览------SQL 标准定义四种隔离级别:

隔离级别 简称 脏读 不可重复读 幻读 实现方式 InnoDB 默认
读未提交 RU
读已提交 RC ✔️ MVCC
可重复读 RR ✔️ ✔️ ❓标准存在,MySQL无 MVCC + 间隙锁
串行化 Serializable ✔️ ✔️ ✔️ 加锁

MySQL InnoDB 在可重复读(RR)级别下,可通过 间隙锁(Gap Lock) 避免幻读。


四、什么是 MVCC(多版本并发控制)

MVCC 的核心目标是:

允许多事务并发读写,并尽量避免加锁阻塞,从而提高性能

其本质是在数据上维护多个版本,通过快照读来实现非阻塞读取。

简单来说就是:它是mysql在innodb存储引擎下实现rr和rc的一种手段,它通过维护行记录的多个不同的版本,通过链的形式连接起来,然后比如在select的时候通过MVCC机制去判断到底用哪一个版本。

具体实现主要分为三大部分:两个主要的隐藏字段,undo版本链,ReadView


MVCC 依赖的关键结构

名称 作用
行隐藏字段 trx_id 表示版本由哪个事务创建
行隐藏字段 roll_pointer 指向 undo log 中的上一个版本
Undo Log(版本链) 保存历史版本,实现回滚和多版本访问
ReadView(读视图) 决定事务能看到哪些版本

undo版本链示例(越下越旧)

cpp 复制代码
最新版本 (trx_id = 20)
      ↓ roll_pointer
上一个版本 (trx_id = 18)
      ↓ roll_pointer
更旧版本 ...

五、ReadView(快照)可见性规则

事务读取数据时,根据版本的 trx_id 判断可见性:

判断条件 能否访问 说明
trx_id == 当前事务ID 自己的版本可读
trx_id < min_trx_id 版本创建事务已提交
trx_id ≥ max_trx_id 版本在快照之后才开始创建
min_trx_id ≤ trx_id < max_trx_id 且在 m_ids 中 创建事务未提交
min_trx_id ≤ trx_id < max_trx_id 且不在 m_ids 中 创建事务已提交

不可见时则通过 roll_pointer 找到可读的历史版本。

最后:要么查不到(都不符合可见性条件),要么查到的就是该事务能看到的"最新合法版本"


六、RC 与 RR 的根本区别:ReadView 生成时机不同

隔离级别 生成策略 导致现象
读已提交(RC) 每次查询都会生成新 ReadView 数据可见版本会变化 → 会出现不可重复读
可重复读(RR) 仅第一次查询创建 ReadView 并复用 快照固定 → 保证可重复读

一句话理解:

RR 固定快照,RC 不固定快照 → RC 更实时,RR 更一致性能


七、总结

控制手段 主要作用 局限性
MVCC 避免读写阻塞,性能好 单独无法完全杜绝幻读
间隙锁 解决幻读问题 降低并发性能
串行化 强一致性 性能最差

总结一句话

InnoDB 通过 MVCC + 锁机制 实现高并发下的事务隔离,RR 默认隔离级别结合间隙锁避免幻读,保证数据一致性。

相关推荐
自不量力的A同学6 小时前
Redisson 4.2.0 发布,官方推荐的 Redis 客户端
数据库·redis·缓存
Exquisite.6 小时前
Mysql
数据库·mysql
全栈前端老曹6 小时前
【MongoDB】深入研究副本集与高可用性——Replica Set 架构、故障转移、读写分离
前端·javascript·数据库·mongodb·架构·nosql·副本集
R1nG8636 小时前
CANN资源泄漏检测工具源码深度解读 实战设备内存泄漏排查
数据库·算法·cann
阿钱真强道7 小时前
12 JetLinks MQTT直连设备事件上报实战(继电器场景)
linux·服务器·网络·数据库·网络协议
逍遥德7 小时前
Sring事务详解之02.如何使用编程式事务?
java·服务器·数据库·后端·sql·spring
笨蛋不要掉眼泪7 小时前
Redis哨兵机制全解析:原理、配置与实战故障转移演示
java·数据库·redis·缓存·bootstrap
Coder_Boy_7 小时前
基于SpringAI的在线考试系统-整体架构优化设计方案
java·数据库·人工智能·spring boot·架构·ddd
fen_fen16 小时前
Oracle建表语句示例
数据库·oracle
砚边数影17 小时前
数据可视化入门:Matplotlib 基础语法与折线图绘制
数据库·信息可视化·matplotlib·数据可视化·kingbase·数据库平替用金仓·金仓数据库