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 默认隔离级别结合间隙锁避免幻读,保证数据一致性。

相关推荐
v***7941 小时前
MySQL篇之对MySQL进行参数优化,提高MySQL性能
数据库·mysql
q***73551 小时前
在Spring Boot项目中使用MySQL数据库
数据库·spring boot·mysql
z***02601 小时前
GaussDB数据库中SQL诊断解析之配置SQL限流
数据库·sql·gaussdb
s***55811 小时前
【MySQL】RedHat8安装mysql9.1
数据库·mysql·adb
笨笨没好名字1 小时前
AI4CAD:用python+creo实现批量参数建模(creo二次开发示例)
数据库·python·microsoft
f***45321 小时前
PostgreSQL常用时间函数与时间计算提取示例说明
数据库·postgresql
e***v3561 小时前
redis分页查询
数据库·redis·缓存
9***44632 小时前
MSSQL2022的一个错误:未在本地计算机上注册“Microsoft.ACE.OLEDB.16.0”提供程序
数据库·microsoft
红石榴花生油2 小时前
RBAC权限配置 核心笔记
数据库·windows·笔记