事务是关系型数据库的核心基石,是保障业务数据可靠、一致、安全的核心机制。转账、订单、库存扣减、支付等核心业务,全部依赖数据库事务来规避数据错乱、脏数据、超卖、数据不一致等问题。
本文系统性讲解 MySQL 事务核心知识点:ACID四大特性、四大事务隔离级别、脏读/不可重复读/幻读问题、MVCC多版本并发控制机制,从原理、问题现象、底层实现、面试考点、生产场景全方位拆解,零基础可吃透事务核心原理。
一、数据库事务概述
事务(Transaction)是一组不可分割的SQL执行单元,要么全部执行成功,要么全部执行失败回滚。事务主要用于保证多步数据操作的整体性,避免部分成功、部分失败导致的数据异常。
MySQL InnoDB 引擎支持事务,MyISAM 引擎不支持事务,这也是生产环境全部选用 InnoDB 的核心原因之一。
二、事务四大特性 ACID(面试必背)
ACID 是事务的四大核心特性,分别对应:原子性、一致性、隔离性、持久性,四个特性相互配合,共同保障事务安全。
2.1 原子性(Atomicity)
核心定义:事务是最小执行单元,不可拆分,要么全部成功提交,要么全部失败回滚,不存在中间状态。
底层保障:InnoDB 通过 undo log(回滚日志) 实现原子性。事务执行前记录数据快照,一旦出现异常、程序崩溃、SQL报错,通过 undo log 回滚所有已执行操作,恢复数据原样。
业务场景:转账业务,A扣钱、B加钱,任意一步失败,全部操作撤销,不会出现“A钱少了、B没到账”的异常数据。
2.2 一致性(Consistency)
核心定义:事务执行前后,数据库数据完整性、约束规则始终一致,不会出现非法、错乱、不符合业务规则的数据。
保障范围:包含主键唯一、唯一约束、外键约束、字段非空、业务数据平衡等所有规则。
底层说明:一致性是最终结果,由原子性、隔离性、持久性+数据库约束共同保障,并非单一日志实现。
举例:转账前后,两人账户总金额保持不变,不会凭空多钱、少钱。
2.3 隔离性(Isolation)
核心定义:多个事务并发执行时,事务之间相互隔离、互不干扰,避免并发读写导致的数据异常。
核心痛点:完全隔离会导致性能极差,因此 MySQL 提供四级隔离级别,允许用户在「数据安全性」和「并发性能」之间做取舍。
底层保障:锁机制 + MVCC 多版本并发控制。
2.4 持久性(Durability)
核心定义:事务一旦提交成功,数据会永久写入数据库,即使服务器断电、宕机、重启,数据也不会丢失。
底层保障:InnoDB 通过 redo log(重做日志) 实现持久性。事务提交前先落盘 redo log,数据即使没来得及写入磁盘文件,重启后也会通过 redo log 恢复数据。
2.5 ACID 核心记忆总结
-
原子性:undo log 保障,要么全成、要么全败
-
持久性:redo log 保障,提交即永久生效
-
隔离性:锁 + MVCC 保障,并发事务互不干扰
-
一致性:最终状态正确,由另外三大特性+约束共同保障
三、并发事务三大问题
并发事务未隔离会产生三类数据问题,严重影响业务准确性,也是隔离级别设计的依据:
3.1 脏读(Dirty Read)
定义:一个事务读取到了另一个事务未提交的脏数据,对方事务回滚后,读取的数据失效。
危害:读取临时无效数据,业务逻辑错乱。
3.2 不可重复读(Non-Repeatable Read)
定义:同一个事务内,两次读取同一条数据,结果不一致。因为中途被其他事务更新并提交。
侧重点:针对 单行数据更新。
3.3 幻读(Phantom Read)
定义:同一个事务内,两次范围查询,查到了新增/消失的数据行。
侧重点:针对 数据行新增、删除,不是单行修改。
四、四大事务隔离级别(面试超级重点)
MySQL 提供四种隔离级别,从低到高安全性递增、性能递减。InnoDB 默认隔离级别为:可重复读(RR)。
4.1 读未提交(Read Uncommitted)
最低隔离级别,允许事务读取其他事务未提交数据。
问题:脏读、不可重复读、幻读全部存在
使用场景:几乎不用
4.2 读已提交(Read Committed,RC)
事务只能读取其他事务已提交的数据。
解决:彻底杜绝脏读
存在问题:不可重复读、幻读
特点:每次读取都会获取最新快照,数据实时性高
4.3 可重复读(Repeatable Read,RR)【MySQL默认】
当前事务开启后,读取的数据始终保持一致,不受其他事务更新影响。
解决:脏读、不可重复读
存在问题:存在幻读(InnoDB 通过间隙锁极大缓解幻读,但未彻底解决)
优势:平衡性能与数据安全,是MySQL默认级别
4.4 串行化(Serializable)
最高隔离级别,事务串行执行,完全禁止并发。
解决:脏读、不可重复读、幻读全部解决
缺点:并发性能极差,锁竞争严重,几乎不用于线上业务
4.5 隔离级别对照表(必背)
| 隔离级别 | 脏读 | 不可重复读 | 幻读 | 性能 |
|---|---|---|---|---|
| 读未提交 | 存在 | 存在 | 存在 | 最高 |
| 读已提交 RC | 不存在 | 存在 | 存在 | 较高 |
| 可重复读 RR(默认) | 不存在 | 不存在 | 存在(缓解) | 中等 |
| 串行化 | 不存在 | 不存在 | 不存在 | 最低 |
五、MVCC 多版本并发控制(核心难点)
MVCC(Multi-Version Concurrency Control)是 InnoDB 实现高并发、无锁读、事务隔离的核心机制。
简单理解:MVCC 就是通过保存数据历史版本,让读操作不加锁,实现读写并发互不阻塞。
5.1 MVCC解决的核心问题
-
解决普通加锁读写互斥、并发性能低的问题
-
实现 RC、RR 隔离级别
-
实现快照读(不加锁查询),极大提升并发能力
5.2 MVCC 三大核心隐藏字段
InnoDB 每一行数据都自带三个隐藏字段,是 MVCC 实现的基础:
-
DB_TRX_ID:最近修改该行数据的事务ID
-
DB_ROLL_PTR:回滚指针,指向 undo log 历史版本数据
-
DB_ROW_ID:隐藏行ID(无主键时作为聚集索引)
5.3 版本链原理
每次事务修改数据,都会生成新数据版本,旧版本数据存入 undo log,通过回滚指针串联成数据版本链。
MVCC 会根据事务快照,从版本链中筛选出「当前事务可见的数据版本」。
5.4 Read View 读视图(核心规则)
Read View 是事务查询时的一致性快照,用来判断哪个版本的数据对当前事务可见。包含核心字段:
-
m_ids:当前活跃未提交的事务ID集合
-
min_trx_id:活跃事务最小ID
-
max_trx_id:下一个待分配事务ID
-
creator_trx_id:当前事务ID
5.5 RC 与 RR 级别下 MVCC 区别(面试高频)
1. 读已提交 RC
每次 SELECT 都会生成新 Read View,每次读取都是最新快照,因此可以读到别人已提交的修改,产生不可重复读。
2. 可重复读 RR(默认)
事务内第一次 SELECT 生成 Read View,后续复用,全程快照一致,因此解决不可重复读。
RR 无法彻底解决幻读,但配合间隙锁+临键锁,业务层面基本杜绝幻读现象。
5.6 当前读 vs 快照读(必懂)
快照读(MVCC)
普通 SELECT 查询,不加锁、非阻塞、读历史快照数据,性能高。
SELECT * FROM table WHERE id = 1;
当前读(加锁读)
读取最新数据,加锁阻塞,无 MVCC 快照机制。
INSERT / UPDATE / DELETE / SELECT ... FOR UPDATE / LOCK IN SHARE MODE
六、高频面试总结(直接背诵)
-
undo log 保证原子性,redo log 保证持久性
-
脏读:读未提交数据;不可重复读:同事务两次读不同(单行更新);幻读:同事务范围查询数据行数变化(新增/删除)
-
RC 解决脏读,RR 解决脏读+不可重复读,串行化解决所有问题
-
MVCC 核心:undo log 版本链 + Read View 快照控制
-
RC 每次查询刷新快照,RR 事务级快照,因此RR可重复读
-
MVCC 只作用于普通快照读,当前读走锁机制