1. ACID 属性
1.1 四大特性
| 属性 | 含义 | InnoDB 实现机制 |
|---|---|---|
| Atomicity(原子性) | 事务要么全完成,要么全不完成 | Undo Log(回滚日志) |
| Consistency(一致性) | 事务前后数据库处于一致状态 | 约束、触发器、外键、业务规则 |
| Isolation(隔离性) | 并发事务互不干扰 | MVCC + 锁 |
| Durability(持久性) | 事务提交后数据永久保存 | Redo Log + WAL(预写日志) |
1.2 InnoDB 的事务日志
Undo Log(回滚日志):
- 记录数据修改前的旧值
- 事务回滚时,用 Undo Log 恢复数据
- 作用:原子性 + MVCC 版本链
Redo Log(重做日志):
- 记录数据修改后的新值
- 事务提交时,先写 Redo Log,再刷脏页
- 作用:持久性(崩溃恢复)
Write-Ahead Logging (WAL):
- 先写日志,再写磁盘
- 日志顺序写(快) vs 数据页随机写(慢)
- Redo Log 顺序写提高性能,同时保证不丢数据
2. 四种隔离级别
SQL 标准定义了四种隔离级别,从低到高限制越来越严格,但并发性能逐渐降低。
| 隔离级别 | 脏读 | 不可重复读 | 幻读 | InnoDB 实现 |
|---|---|---|---|---|
| READ UNCOMMITTED | ✅ 允许 | ✅ 允许 | ✅ 允许 | 直接读取最新版本 |
| READ COMMITTED | ❌ 禁止 | ✅ 允许 | ✅ 允许 | MVCC(每次读生成 ReadView) |
| REPEATABLE READ | ❌ 禁止 | ❌ 禁止 | ⚠️ InnoDB 禁止 | MVCC + 间隙锁 |
| SERIALIZABLE | ❌ 禁止 | ❌ 禁止 | ❌ 禁止 | 所有 SELECT 加锁 |
2.1 三种并发异常
脏读(Dirty Read)
事务 A 事务 B
│ │
├──→ 修改余额 = 800
│ (未提交) │
│ ├──→ 读取余额 = 800 ← 脏读!
│ │
├──→ ROLLBACK(回滚)
│ 余额恢复 1000 │
│ │
│ ├──→ 之前读到的 800 是错误数据
不可重复读(Non-repeatable Read)
事务 A 事务 B
│ │
├──→ 读取余额 = 1000 │
│ ├──→ 修改余额 = 800
│ │ COMMIT
│ │
├──→ 再次读取余额 = 800 ← 同一事务内两次读取结果不同!
幻读(Phantom Read)
事务 A 事务 B
│ │
├──→ SELECT COUNT(*) FROM orders
│ 结果: 10 条 │
│ ├──→ INSERT INTO orders ...
│ │ COMMIT
│ │
├──→ SELECT COUNT(*) FROM orders
│ 结果: 11 条 ← 同一事务内两次范围查询行数不同!
2.2 InnoDB 的 RR 如何解决幻读
InnoDB REPEATABLE READ 下:
- 快照读(普通 SELECT):通过 MVCC + ReadView(事务首次 SELECT 时生成)
→ 整个事务看到一致快照,不会出现幻影行
- 当前读(SELECT ... FOR UPDATE):通过 Next-Key Lock(记录锁 + 间隙锁)
→ 锁定查询范围及间隙,阻止其他事务插入新行
注意:SQL 标准中 RR 允许幻读,但 InnoDB 通过上述机制实际上在大部分场景下解决了幻读。
3. 隔离级别设置
-- 查看当前隔离级别
SELECT @@transaction_isolation;
-- 设置会话级隔离级别
SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;
SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ;
SET SESSION TRANSACTION ISOLATION LEVEL SERIALIZABLE;
-- 启动事务
START TRANSACTION;
-- 或
BEGIN;
-- 提交 / 回滚
COMMIT;
ROLLBACK;
4. 隔离级别选择建议
| 场景 | 推荐隔离级别 | 原因 |
|---|---|---|
| 普通 OLTP 应用 | READ COMMITTED | 避免锁竞争,Oralce/PostgreSQL 默认 |
| 金融交易、对账 | REPEATABLE READ | MySQL 默认,防不可重复读 |
| 报表统计(快照一致性) | REPEATABLE READ | 事务内数据一致 |
| 极端严格同步 | SERIALIZABLE | 性能代价高,一般不用 |
注意:MySQL 默认 RR,Oracle/PostgreSQL/SQL Server 默认 RC。MySQL 的 RR 配合 MVCC 在很多场景下并不比 RC 锁更多。
延伸阅读
继续阅读
探索更多技术文章
浏览归档,发现更多关于系统设计、工具链和工程实践的内容。