MySQL 事务原理 + ACID笔记
一、事务简介
事务(Transaction) 是一组数据库操作的逻辑单元,这些操作要么全部成功,要么全部失败。事务的核心是保证数据的完整性和一致性。
事务必须满足 ACID 四大特性:
- A(Atomicity,原子性)
- C(Consistency,一致性)
- I(Isolation,隔离性)
- D(Durability,持久性)
MySQL 事务的实现主要依赖 InnoDB 引擎,通过 日志 + 锁 + MVCC 来保证 ACID。
二、ACID 四大特性及实现原理
1. A — 原子性(Atomicity)
定义:
事务是一个不可分割的整体,要么全部执行成功,要么全部回滚,不允许部分成功。
实现机制:Undo Log(回滚日志)
-
作用:记录数据被修改前的状态,用于回滚操作。
-
原理:
- 事务执行
UPDATE/DELETE/INSERT
时,会先记录修改前的旧值到 Undo Log。 - 如果事务失败或执行
ROLLBACK
,通过 Undo Log 恢复到原始状态。
- 事务执行
-
存储位置:系统表空间或独立的 Undo 表空间。
-
额外作用:Undo Log 也用于 MVCC 提供一致性读。
示例:
START TRANSACTION;
UPDATE account SET balance = balance - 100 WHERE id = 1;
UPDATE account SET balance = balance + 100 WHERE id = 2;
ROLLBACK; -- 通过 Undo Log 回滚
2. C — 一致性(Consistency)
定义:
事务执行前后,数据库必须从一个一致状态转换到另一个一致状态,不能违反完整性约束。
实现方式:
- 完整性约束(主键、外键、CHECK)
- 事务控制(失败时回滚)
- 双写缓冲(Double Write):避免部分数据页损坏。
一致性不是单独依靠某个日志实现,而是 ACID 其他特性 + 约束机制共同保证的。
3. I — 隔离性(Isolation)
定义:
多个事务并发执行时,它们的操作不能互相干扰。
实现机制:
-
MVCC(Multi-Version Concurrency Control,多版本并发控制)
-
原理:
- 每行数据有多个版本(由 Undo Log 记录)。
- 事务读取数据时,通过 Read View 获取符合当前隔离级别的版本。
-
适用于一致性读(普通
SELECT
)。
-
-
锁机制
- 行锁(Record Lock)
- 间隙锁(Gap Lock)
- Next-Key Lock(Record Lock + Gap Lock,防止幻读)
隔离级别及问题:
隔离级别 | 脏读 | 不可重复读 | 幻读 |
---|---|---|---|
READ UNCOMMITTED | ✅ | ✅ | ✅ |
READ COMMITTED | ❌ | ✅ | ✅ |
REPEATABLE READ | ❌ | ❌ | ✅(InnoDB 通过间隙锁避免) |
SERIALIZABLE | ❌ | ❌ | ❌ |
查看 & 设置隔离级别:
SELECT @@tx_isolation;
SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ;
4. D — 持久性(Durability)
定义:
事务提交后,修改的数据必须永久保存,即使系统宕机也能恢复。
实现机制:Redo Log(重做日志)+ WAL + Double Write
-
Redo Log(InnoDB 专用)
-
作用:记录事务对数据页的物理修改,用于崩溃恢复。
-
WAL(Write Ahead Logging)原则:先写日志,再写数据页。
-
流程:
- 修改数据 → 写入 Buffer Pool。
- 生成 Redo Log(Prepare 阶段)。
- 提交事务,Redo Log 写入磁盘(Commit 阶段)。
- 异步将数据页刷盘。
-
-
Double Write
- 防止数据页写一半导致损坏。
- 先写入 Double Write Buffer,再写到表空间。
-
binlog(二进制日志)
- 用于主从复制和恢复,不直接保证事务 ACID,但与 Redo Log 一起用于崩溃恢复。
参数:
SHOW VARIABLES LIKE 'innodb_flush_log_at_trx_commit';
1
:每次提交都刷盘,最安全。2
:写 OS 缓存,1 秒后刷盘,性能更好。0
:每秒刷盘,不推荐。
三、MySQL 事务执行流程
SQL 执行 → 生成 Undo Log → 修改 Buffer Pool → 写 Redo Log (Prepare) → 写 binlog → Redo Log (Commit) → 刷盘
对应 ACID:
- A(原子性) → Undo Log
- C(一致性) → 约束 + 回滚 + Double Write
- I(隔离性) → MVCC + 锁
- D(持久性) → Redo Log + WAL
四、Redo Log、Undo Log、binlog 区别
日志类型 | 作用 | 保证特性 | 内容 |
---|---|---|---|
Undo Log | 回滚、MVCC | 原子性 | 修改前数据 |
Redo Log | 崩溃恢复(物理日志) | 持久性 | 数据页修改 |
binlog | 主从复制、恢复 | 审计 & 恢复 | 逻辑操作 |
五、面试高频问答
Q1:MySQL 如何保证事务的原子性?
- 通过 Undo Log,记录修改前的数据,用于回滚。
Q2:MySQL 如何保证持久性?
- Redo Log + WAL + Double Write,提交后即使宕机也能恢复。
Q3:MySQL 隔离性如何实现?
- MVCC + 锁。MVCC 处理一致性读,锁处理当前读。
Q4:Redo Log 和 binlog 区别?
- Redo Log:物理日志,InnoDB 专用,用于崩溃恢复。
- binlog:逻辑日志,所有引擎通用,用于主从复制和数据恢复。
Q5:事务提交的两阶段提交是什么?
- Prepare:Redo Log 写入磁盘(不可见)。
- Commit:binlog 写入磁盘后,再提交 Redo Log。
六、关键 SQL & 配置
-- 查看隔离级别
SELECT @@tx_isolation;-- 设置隔离级别
SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ;-- 查看事务参数
SHOW VARIABLES LIKE 'innodb_flush_log_at_trx_commit';
SHOW VARIABLES LIKE 'autocommit';
七、图解
事务执行流程图:
Client SQL↓
生成 Undo Log(原子性)↓
修改 Buffer Pool↓
写 Redo Log (Prepare)↓
写 binlog↓
Redo Log (Commit)↓
刷盘(持久性)