章节摘要:前三章解决了"怎么存、怎么执行",本章解决"怎么不出错"。SQLite 在单文件上兑现 ACID 靠的是页级日志:默认的回滚日志在覆盖旧页前先把原页抄走,WAL 模式则反过来把新页追加到伴生文件。本章拆解事务的字节码与页级账本,枚举 journal_mode 五种模式的取舍,逐帧解析 WAL 文件结构与检查点机制,最后对照三个引擎的锁与隔离体系。读完本章,你能解释"为什么开 WAL 后读写不再互斥"以及"什么情况下 WAL 文件会无限增长"。
读完本章,你应当能够:
一句金句:回滚日志保护"还没写完的旧世界",WAL 保护"已经写好的新世界"——方向一换,读写的命运就分开了。
4.1 事务模型与页级账本:事务在 VDBE 字节码里长什么样,pager 怎么用 journal 记账,提交点在哪一毫秒,崩溃恢复怎么回放账本;附带 SAVEPOINT 存档点的工程用法。
4.2 journal 模式五态:五种模式的磁盘行为逐一对照,给出选择决策表;顺带回答"synchronous 参数和 journal 模式是什么关系"与"切换失败怎么排查"。
4.3 WAL 文件结构与检查点:帧格式、盐值防串页、校验和防撕裂、检查点的三种力度与默认阈值,以及 WAL 增长的四个常见病因与运维实操命令。
4.4 锁与隔离三库对照:SQLite 的文件锁状态机与 WAL 快照隔离,对照 InnoDB 行锁间隙锁与 PostgreSQL 的 MVCC 多版本,BUSY 错误的重试模板与 DEFERRED、IMMEDIATE 的选择。
四节按"先回滚后 WAL"的顺序排布,因为 WAL 的每个设计决定都是对回滚日志某个缺点的回应:4.1 先建立"日志即页账本"的基线,4.2 枚举基线的调优空间,4.3 引入追加日志的新架构,4.4 展示新架构释放的并发能力及其边界。学完你会发现两种日志本质是同一道题的两个答案:
4.1 页级账本(回滚) ──▶ 4.2 模式五态 ──▶ 4.3 WAL 追加日志 ──▶ 4.4 并发与隔离 旧世界怎么保住 中间形态盘点 新世界怎么落盘 读者与写者分家 │ ▼ 第8章:备份与恢复就是账本机制的运维面
前置:第 2 章的页概念(日志的单位就是页);第 3 章的字节码基础(看懂 BEGIN、COMMIT 指令即可)。
后续延伸:第 7 章的 page cache 在事务里扮演"脏页仓库";第 8 章的备份三招全部建立在"日志保证文件处于一致状态"之上。带着问题读:WAL 模式下,一个读事务怎么在写入不断发生的同时看到稳定一致的世界?