← 每日面试题 学习看板

MySQL事务ACID是如何实现的?

面试题/03数据库中间件/01MySQL/01数据库基础概念与核心特性/MySQL事务ACID是如何实现的?.md

面试记录 2026-09-17

题目:MySQL 事务 ACID 是如何实现的?

难度:medium

标签:db/mysql/concepts, mysql/acid, mysql/transaction, difficulty/medium

评分:⭐⭐☆☆(2/5)

我的回答

首先明确下 MySQL 事务的 ACID 都是什么?原子性、一致性、隔离性、持久性。原子性的话基本上是通过锁来执行的,以及 undo log 重做日志去保证。隔离性的话是通过锁,隔离是通过锁,行锁、表锁、间隙锁这些东西把不同的事务进行隔离。持久性就是 binlog 跟 binlog 日志去实现的持久性,然后把数据存到 binlog 以及磁盘文件实现持久性。最终通过原子、隔离、持久三个性质一致。三个性质来实现一致性。

点评

优点:

不足:

补充:

完整讲解

第一部分:知识重点剖析

核心考点定位:掌握 ACID 每个性质在 InnoDB 里的具体实现机制,尤其是 redo log、undo log、MVCC、锁、2PC 的分工。

知识点拆解:

  1. A - Atomicity(原子性)
  1. C - Consistency(一致性)
  1. I - Isolation(隔离性)
  1. D - Durability(持久性)
  1. 关键日志对比:
日志层级记录内容主要用途
undo logInnoDB 引擎层旧值(逻辑)回滚 + MVCC
redo logInnoDB 引擎层物理页修改崩溃恢复(WAL)
binlogMySQL Server 层逻辑 SQL / row主从复制 + 灾备
  1. 关键参数:

第二部分:考察方向与延伸递进

考察方向:

延伸递进面试题:

  1. redo log 和 binlog 都是"日志",为什么不能只用一个?
  1. 2PC 的作用是什么?为什么不能只在 InnoDB 里提交?
  1. innodb_flush_log_at_trx_commit=2 什么时候用?

第三部分:面试者参考回答(口语化)

面试官您好,MySQL 事务的 ACID 我按每个字母拆开讲。

原子性靠 undo log 实现。undo log 是回滚日志,记录每次修改的旧值。事务回滚时按 undo log 反向重放,把数据恢复到事务开始前的状态。崩溃恢复时也一样,未提交的事务用 undo log 回滚。

一致性其实是数据库 + 业务共同保证的。数据库本身只保证 A、I、D 三个性质,业务一致性需要靠约束(NOT NULL、UNIQUE、外键)加上事务边界内正确的业务代码。比如转账 A 减 100、B 加 100,两条 SQL 必须在同一个事务里,靠原子性保证要么都成功要么都失败。

隔离性主要靠锁和 MVCC 两套机制。写操作和当前读(SELECT FOR UPDATE、UPDATE、DELETE)用悲观锁,包括行锁、间隙锁、next-key lock;快照读(普通 SELECT)用 MVCC,通过 ReadView 判断行的哪个版本对当前事务可见,不需要加锁。两套机制配合解决了脏读、不可重复读和部分幻读。

持久性靠 redo log 和 2PC 实现,跟 binlog 是分开的。redo log 是 InnoDB 引擎层的物理日志,记录哪个页的哪字节改成什么。事务提交时把 redo log 刷盘,用 WAL(Write-Ahead Logging)机制保证——先写日志再改内存页,崩溃后用 redo 重放未落盘的页修改。这里要注意 innodb_flush_log_at_trx_commit=1 才能确保每次都刷,不然可能丢数据。

binlog 是 MySQL Server 层的逻辑日志,主要用于主从复制和灾备恢复,不是持久性的直接保证。redo 和 binlog 通过 2PC(两阶段提交) 联动:InnoDB 先写 redo log 状态 prepare,然后写 binlog,最后把 redo 状态改成 commit。崩溃恢复时根据 redo 和 binlog 的状态判断是提交还是回滚。

所以三个日志的分工是:undo log 负责回滚(原子性)、redo log 负责崩溃恢复(持久性)、binlog 负责复制和灾备。生产环境通常用"双 1 配置"——sync_binlog=1 + innodb_flush_log_at_trx_commit=1,两个日志都每次刷盘,保证不丢事务。