WAL:为什么数据库要先写日志,再写真正数据?

TL;DR

WAL 要求描述数据变化的日志先于数据页持久化,让数据库可以延迟刷写并在崩溃后通过重放恢复。本文用账本和收据解释 REDO、检查点、复制与持久性设置的关系。

WAL 要求描述数据变化的日志先于数据页持久化,让数据库可以延迟刷写并在崩溃后通过重放恢复。本文用账本和收据解释 REDO、检查点、复制与持久性设置的关系。

WAL:为什么数据库要先写日志,再写真正数据?

数据库为什么不直接把修改写进表文件,而要先写一份日志?因为真实世界的磁盘写入可能被中断:机器掉电、进程崩溃、文件系统只完成了一半写入。WAL,Write-Ahead Logging,预写式日志,提供了一条恢复线索:数据页真正落盘前,描述这次修改的日志必须先被持久化。

先写日志,再写数据

事务提交时,数据库不必立刻把所有表页和索引页都刷到磁盘,只要确保对应的 WAL 记录已经安全写入。发生崩溃后,数据库可以从日志重放尚未应用到数据页的修改,这就是 roll-forward 或 REDO 恢复。

这个顺序非常关键。如果数据页先写了一部分,日志却没有记录完整,崩溃后系统就可能无法知道应该恢复什么。相反,只要日志足够完整,数据页晚一点写也可以接受。

WAL 不是普通日志文件

应用日志主要帮助人类排查问题;WAL 是数据库恢复协议的一部分,记录格式、顺序、刷盘时机和检查点都有严格语义。它还可以用于复制、时间点恢复和崩溃后的重放。

WAL 也有代价:日志会占用磁盘和 I/O 带宽,需要归档、清理和监控。高写入量系统必须关注日志生成速度、刷盘延迟、检查点压力和复制滞后。关闭或放松持久性设置,可能换来速度,但也会改变故障后的数据保证。

AI 编程时别只写“保存成功”

一个 API 返回成功,不一定代表数据已经安全写入所有层。设计订单、支付或任务队列时,需要明确事务提交点、崩溃恢复策略和重复重放行为。WAL 的思想也启发了很多系统:先记录可恢复事实,再异步整理最终结构。

读者应该记住

WAL 把数据库的可靠性建立在一条顺序上:描述变化的日志必须先于数据变化持久化。它让数据库能够快速提交、延迟刷数据,并在崩溃后通过重放恢复。

资料:PostgreSQL:Write-Ahead Logging

KEEP READING