第3章 事务与并发控制
事务与并发控制是数据库内核面试的核心,约占大厂面试题的 35%。本章从 ACID 实现机制、MVCC 原理、死锁处理三个高频考点切入,配合真实项目案例,帮你构建从理论到工程的回答体系。
📌 面试问题 1 — 事务 ACID 特性与 InnoDB 实现
- 是否理解 ACID 四个特性的语义差异
- 是否掌握 undo log / redo log / 锁 / MVCC 等底层机制
- 能否将理论与工程组件对应起来
- 一句话总述 ACID 是事务的四大保证
- 原子性 → undo log(回滚时撤销操作)
- 一致性 → 约束检查 + 日志 + 并发控制共同保证
- 隔离性 → 锁 + MVCC 提供四种隔离级别
- 持久性 → redo log + WAL 策略确保提交不丢失
ACID 是事务四大特性。原子性通过 undo log 实现,回滚时撤销已执行操作;一致性由约束、日志和并发控制共同保证;隔离性通过锁和 MVCC 实现;持久性依靠 redo log 和 WAL 策略,确保提交后数据不丢失。
- undo log 和 redo log 在崩溃恢复时的协作流程是怎样的?
- 双写缓冲(doublewrite buffer)如何保证持久性?
不要只背诵 ACID 定义而忽略实现机制;特别注意区分 undo log 负责原子性、redo log 负责持久性,不可混淆;提到隔离性时必须关联锁与 MVCC 两种手段。
📌 面试问题 2 — MVCC 实现原理与隔离级别差异
- 对 MVCC 底层组件(事务 ID、版本链、read view)的理解
- RC 与 RR 级别下 read view 创建时机的差异
- MVCC 如何解决读写冲突而不阻塞
- MVCC 核心目标:读写不互斥
- 三个组件:事务 ID、undo log 版本链、read view
- 每行记录隐藏字段 db_trx_id / db_roll_ptr 构成版本链
- read view 创建时机:RC 每次查询创建,RR 首次查询创建
- 可见性判断:比较事务 ID 与 read view 中的活跃事务列表
MVCC 通过维护数据行多版本实现读写不互斥。每行隐藏事务 ID 和回滚指针构成版本链。read view 是可见性快照,RC 每次查询创建新 read view,可读到已提交更新;RR 仅首次查询创建,实现可重复读。
- MVCC 在 RR 级别下如何避免幻读?(gap lock 配合)
- 长事务对 MVCC 版本链有什么负面影响?
不要只说概念不提组件;必须清晰区分 RC 和 RR 的 read view 创建时机;MVCC 不能单独解决幻读,RR 级别需结合 gap lock;避免将 MVCC 与锁机制完全割裂。
📌 面试问题 3 — 死锁检测算法与处理策略
- 是否理解死锁产生的四个必要条件
- 是否掌握 wait-for graph 等检测算法
- 工程上如何选择牺牲者并优化
- 死锁四个必要条件(互斥/持有等待/不剥夺/循环等待)
- 检测方法:超时检测 vs wait-for graph(有向图检测环)
- 处理策略:选择回滚代价最小的事务作为牺牲者
- 工程优化:规范化加锁顺序、锁超时、死锁检测阈值
死锁检测常用 wait-for graph 算法,检测有向环即死锁。选择回滚代价最小的事务作为牺牲者释放锁。工程上通过规范化加锁顺序、设置锁超时、死锁检测阈值等优化降低死锁发生概率。
- 如何量化"回滚代价最小"?(事务已执行时间/修改行数/日志量)
- 分布式事务中的死锁检测与单机有何不同?
不要只讲四个理论条件而忽略检测算法;wait-for graph 要说明"节点=事务、边=等待关系、环=死锁";提到处理策略时必须包含"选择牺牲者"的考量维度。
🏗 项目案例:高并发交易系统的 MVCC 并发控制优化
金融核心交易系统,日均处理千万级交易,高峰期存在严重读写冲突导致吞吐量急剧下降。
TPS 50,000+,数据量 10 TB+,日均交易量 2,000 万笔,峰值 QPS 12 万。
MySQL 8.0 InnoDB、RocksDB、分布式事务中间件(DTX)、Prometheus + Grafana 监控。
- 热点账户并发更新导致锁竞争激烈,TPS 跌至 8,000
- 长事务导致 MVCC 版本链膨胀,undo 表空间暴涨
- 读写冲突引发大量事务回滚,系统抖动频繁
- 热点行拆分后如何保证全局一致性?(分布式事务/异步对账)
- MVCC 版本链膨胀如何监控和治理?(undo 表空间阈值 + 长事务 kill)
- 降级 RC 隔离级别后如何弥补业务语义?(业务幂等 + 乐观锁重试)
我们通过分析慢查询和锁等待日志,定位热点账户为瓶颈。采用三方面优化:热点行拆分子账户分散锁竞争;监控长事务并设超时阈值防版本链膨胀;业务允许场景降级 RC 隔离级别减少 gap lock。最终 TPS 从 1.2 万提升至 5 万+。
| 隔离级别 | 脏读 | 不可重复读 | 幻读 | 内核实现机制 |
|---|---|---|---|---|
| READ UNCOMMITTED | 可能 | 可能 | 可能 | 不加锁,直接读取最新版本 |
| READ COMMITTED | 避免 | 可能 | 可能 | MVCC + 行锁,每次查询创建 read view |
| REPEATABLE READ | 避免 | 避免 | 可能(InnoDB gap lock 可避免) | MVCC + gap lock / next-key lock |
| SERIALIZABLE | 避免 | 避免 | ← 上一章 📖 返回目录 下一章 → |