{ "topic": "mysql-acid", "type": "short_answer", "schema_version": "1.0.0", "generated": "2026-09-07T00:00:00+08:00", "questions": [ { "id": "sa-001", "type": "short_answer", "difficulty": 2, "tags": [ "ACID", "原子性", "undo log", "InnoDB" ], "question": "解释 InnoDB 如何用 undo log 实现事务的原子性(回滚)。", "answer": "InnoDB 在每个事务执行写操作时,先把旧值(修改前的数据)写入 undo log。若事务需要回滚或崩溃恢复时确定未提交,InnoDB 依据 undo log 中记录的旧值做逆操作:INSERT 对应 DELETE 反操作、DELETE 对应重新插入、UPDATE 则把新旧值互换改回,从而把数据恢复到事务开始前的状态。整个事务要么全部提交要么全部回滚,即为原子性。", "keywords": [ "undo log", "旧值", "逆序回滚", "原子性" ], "scoring_rubric": "总分 4 分:说明修改前写 undo log(2 分);说明用旧值逆序回滚(2 分)。", "explanation": "核心是“记录旧值 + 逆操作回滚”。答出 undo log 记录旧值、支持把数据恢复到事务前状态即可得分。", "source": null, "related": [] }, { "id": "sa-002", "type": "short_answer", "difficulty": 3, "tags": [ "持久性", "redo log", "WAL", "InnoDB" ], "question": "什么是 Write-Ahead Logging(WAL)?它在 MySQL InnoDB 中如何保证持久性?", "answer": "WAL 指“先写日志再写数据”:任何数据页的修改在落盘之前,必须先把对应的 redo log 记录写入磁盘并持久化。InnoDB 修改 Buffer Pool 中的页时会先向 redo log 追加物理变更;事务提交时确保该 redo 已写入磁盘(fsync,或按 innodb_flush_log_at_trx_commit 决定)。若在数据页落盘前崩溃,重启时通过扫描并重放 redo log,把已提交事务的修改恢复到数据文件,因此已提交数据不会丢失,从而保证持久性。", "keywords": [ "WAL", "先写日志再写数据", "redo log", "重放恢复", "持久性" ], "scoring_rubric": "总分 4 分:给出 WAL 定义“先写日志后写数据”(2 分);说明崩溃重放 redo 恢复(1 分);结合 InnoDB 描述(1 分)。", "explanation": "先陈述 WAL 的顺序要点,再联系 redo log 在这次重放(redo)与 fsync 的细节,符合本主题核心理解。", "source": null, "related": [] }, { "id": "sa-003", "type": "short_answer", "difficulty": 3, "tags": [ "redo log", "物理日志", "undo log", "逻辑日志" ], "question": "对比 redo log 与 undo log 在记录内容(物理/逻辑)和作用上的区别。", "answer": "两者差异如下:1)记录内容:redo log 是物理日志,记录了对哪个数据页哪一处的字节所做的实际修改;undo log 是逻辑日志,记录如何把一行数据“改回旧值”的逆操作。2)作用方向:redo 用于崩溃后重做(REDO)已提交事务,保证持久性;undo 用于回滚未提交事务(或 MVCC 提供历史版本)保证原子性与隔离读。redo 是能重做的物理重放,undo 是可逆回滚的逻辑逆操作。", "keywords": [ "redo 物理", "undo 逻辑", "重做已提交", "回滚未提交", "崩溃恢复" ], "scoring_rubric": "总分 4 分:redo 物理日志(1 分);undo 逻辑日志(1 分);redo 重做已提交(1 分);undo 回滚未提交(1 分)。", "explanation": "分别从“物理 vs 逻辑”“重做 vs 回滚”两个维度对比,即可覆盖核心差异。", "source": null, "related": [] }, { "id": "sa-004", "type": "short_answer", "difficulty": 4, "tags": [ "崩溃恢复", "redo log", "undo log", "InnoDB" ], "question": "详细描述 InnoDB 崩溃恢复的三阶段流程。", "answer": "第一阶段(扫描 redo log):从 redo 中确定本次恢复需要处理的 lSN 范围与 checkpoint 位置,找出需要重做的日志段。第二阶段(重做已提交事务):按 redo log 将崩溃前已提交但尚未刷盘到数据文件的数据页修改重新应用(redo ),使这些已提交的修改得到恢复。第三阶段(回滚未提交事务):通过两阶段提交记录的 xid 识别哪些事务未在 binlog 中完整提交,利用 undo log 把这些未提交事务的执行进行回滚,最终使数据库恢复到崩溃前一致、没有丢失已提交数据且无未提交改动残留的状态。", "keywords": [ "扫描 redo", "重做已提交", "回滚未提交", "两阶段提交", "checkpoint" ], "scoring_rubric": "总分 4 分:扫描 redo 确定范围(1 分);重做已提交事务(2 分);用 undo 回滚未提交(1 分)。", "explanation": "按顺序答出重做/回滚的职责与对象判断(以两阶段提交/是否已提交为依据)即可。", "source": null, "related": [] }, { "id": "sa-005", "type": "short_answer", "difficulty": 2, "tags": [ "隔离性", "MVCC", "undo log", "快照读" ], "question": "MVCC 是什么?InnoDB 使用它如何提升并发隔离性?", "answer": "MVCC(多版本并发控制)是 InnoDB 提供一致性非锁定读的机制:通过 undo log 维护每一行的多版本链。当普通 SELECT(快照读)执行时,InnoDB 依据事务的 ReadView(可见性判断)沿版本链找到当前事务可见版本,不需要加共享锁。这样多个读事务与写事务可并发执行,读不被写阻塞,从而在维持隔离性的前提下显著提升并发吞吐。", "keywords": [ "MVCC", "undo log 版本链", "ReadView", "一致性读", "非锁读" ], "scoring_rubric": "总分 3 分:给出 MVCC 定义(1 分);说明 undo 多版本 + ReadView(1 分);读不加锁、提升并发(1 分)。", "explanation": "抓住“多版本链 + ReadView + 读不加锁”即可说明 MVCC 是如何提升并发也保隔离的。", "source": null, "related": [] }, { "id": "sa-006", "type": "short_answer", "difficulty": 3, "tags": [ "隔离性", "行锁", "间隙锁", "next-key lock" ], "question": "在可重复读(RR)隔离级别下,InnoDB 的 next-key lock(临键锁)如何防止幻读?", "answer": "RR 下 InnoDB 对索引范围/查找会加 next-key lock(由行锁 + 间隙锁组成的左开右闭区间锁)。它既锁住命中的记录(行锁),又锁住记录之间的间隙(gap),阻止其他事务在该扫描区间内 INSERT 新行。因为在该被锁定的范围里不可能再插入新记录,当前事务多次查询同一范围结果一致,从而防止了幻读。", "keywords": [ "next-key lock", "gap lock", "锁定区间", "防幻读", "RR" ], "scoring_rubric": "总分 3 分:指出 next-key = 行锁 + 间隙锁(1 分);锁区间阻止插入(1 分);讲到幻读消除(1 分)。", "explanation": "从一个锁出发:锁间区使别人无法插入,故范围查询结果稳定,防幻读。", "source": null, "related": [] }, { "id": "sa-007", "type": "short_answer", "difficulty": 3, "tags": [ "两阶段提交", "redo log", "binlog", "一致性" ], "question": "为什么 MySQL 需要用两阶段提交来协调 redo log 与 binlog?", "answer": "因为同一条事务的修改既要写 redo log(用于崩溃恢复)又要写 binlog(用于复制与恢复),若没协调,崩溃可能发生在一个日志已写另一个未写的时刻,导致主库重放后与从库/恢复点不一致。两阶段提交通过 prepare(redo 先 prepare)+写 binlog+ commit(redo 标记)的划分,并在恢复时以“binlog 是否完整作为事务是否提交”的裁决,保证 redo 与 binlog 的已提交事务集合完全一致,杜绝主从数据不一致与 PITR 偏差。", "keywords": [ "两阶段提交", "prepare", "binlog 为准", "主从一致", "xa" ], "scoring_rubric": "总分 4 分:指出两份日志都需要(1 分);说明子过程 prepare/binlog/commit(1 分);说明以 binlog 为准裁决提交(2 分)。", "explanation": "核心是“防止在日志中间崩溃造成两份日志事务集不一致”,并以 binlog 为裁决者。", "source": null, "related": [] }, { "id": "sa-008", "type": "short_answer", "difficulty": 2, "tags": [ "redo log", "binlog" ], "question": "redo log 与 binlog 各自的应用场景和作用是什么?", "answer": "redo log 是 InnoDB 引擎层专用于崩溃恢复的重做日志(物理记录页修改);binlog 是 MySQL Server 层的逻辑日志,记录事务的逻辑变更,主要场景为主从复制(从库重放 binlog)、基于时间点/位置的恢复 PITR 及审计。redo 在崩溃恢复时让 InnoDB 持久化已提交数据,binlog 面向整个实例的外部同步与运维。", "keywords": [ "redo 崩溃恢复", "binlog 复制", "PITR", "审计" ], "scoring_rubric": "总分 3 分:redo 崩溃重做(1 分);binlog 复制 PITR(1 分);指出层与外部区别(1 分)。", "explanation": "从时间/层和用途三方面对比即可。", "source": null, "related": [] }, { "id": "sa-009", "type": "short_answer", "difficulty": 3, "tags": [ "一致性", "约束", "ACID" ], "question": "解释在 InnoDB 中一致性(Consistency)是如何实现的,并说明它与 A、I、D 的关系。", "answer": "一致性指事务保证数据从一致状态到一致的状态。InnoDB 通过约束(主键、唯一、非空、外键、CHECK 等)保证提交的数据满足完整性,同时一致性依赖于另三者:若原子性被破坏会造成部分写入,隔离性破坏可能读到中间态,持久性破坏会导致状态回退。只有当原子性(全提交或全回滚)、隔离性(并发不受互扰)、持久性(提交可恢复)三者共同成立,配合约束与业务逻辑,才能把已提交事务改变成一个整体一致的状态。", "keywords": [ "约束", "原子性", "隔离性", "持久性", "一致状态" ], "scoring_rubric": "总分 4 分:提到约束(1 分);A/I/D 各自如何维护一致(2 分);说明三者共同保证(1 分)。", "explanation": "一致性不是一个独立机制,而是约束 + A/I/D 的协作者;答出三者影响一致性的链路即好。", "source": null, "related": [] }, { "id": "sa-010", "type": "short_answer", "difficulty": 3, "tags": [ "innodb_flush_log_at_trx_commit", "持久性", "性能" ], "question": "对比 innodb_flush_log_at_trx_commit 取 (0/1/2) 三种值在持久性与性能上的取舍。", "answer": "0:每秒刷一次 redo log 盘,性能直高但进程崩溃会丢近 1 秒已提交事务;1:每次提交都 fsync 刷盘,持久性最强、最安全,但磁盘同步 IO 开销大、提交延迟高;2:每次提交把 redo 写至 OS 缓存(write,不 fsync),MySQL 进程崩溃时数据不丢,但 OS 崩溃/断电可能丢近 1 秒数据,性能比起 1 明显更高、比 0 稍低。生产 Server 建议设置为 1(严格 ACID),对可容忍少量丢亦可 2/0 提升吞吐。", "keywords": [ "0 每秒刷盘", "1 每次 fsync", "2 OS 缓存", "持久性 vs 性能" ], "scoring_rubric": "总分 4 分:0 语义与丢数据(1 分);1 语义持久性最强(1 分);2 写 OS 缓存语义(1 分);指出取舍与推荐(1 分)。", "explanation": "三个取值逐一说明“何时同步 fsync”即可,再补充其与几种崩溃类型的对应关系。", "source": null, "related": [] } ] }