515acbcc7f
Deploy Examination / deploy (push) Successful in 4s
- mysql-acid (35): undo/redo log, WAL, 崩溃恢复三阶段, 两阶段提交 - mysql-transaction-isolation (35): 四隔离级别, 三异常, Read View, 快照读/当前读, next-key lock - redis-persistence (35): RDB/AOF/混合持久化, AOF 重写, vs binlog/redo log - 每子主题: single_choice×10 + fill_blank×10 + short_answer×10 + code_reading×5 - 全部通过 question.schema.json 校验
241 lines
12 KiB
JSON
241 lines
12 KiB
JSON
{
|
||
"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": []
|
||
}
|
||
]
|
||
} |