一句话定义:WAL(Write-Ahead Log,预写日志)是一条规矩——任何要修改数据的操作,必须先把"打算改什么"写进一份只追加的日志并落盘,之后才允许去改真正的数据文件。
为什么需要它
数据库的数据散落在磁盘上许多个页(page)里,想改一条记录往往牵动好几个页,而这些页在磁盘上并不相邻。这种随机写有两个麻烦:一是慢;二是可能只写了一半就断电,留下一个既不是旧值也不是新值的坏页。
日志不一样。它只能往末尾追加,这种顺序写对机械硬盘和 SSD 都友好得多。于是数据库换了个思路:与其硬着头皮把散落的页改对,不如先在日志末尾记一行"第 X 页,把 A 改成 B",立刻落盘,再慢慢去改数据页。
打个比方:后厨接到订单,不会直接开做,而是先把单子钉在出餐口。厨师做到一半晕倒,接手的人看一眼单子,就知道哪几道已经出了、哪几道还欠着。单子上的字,比锅里的菜可靠。
崩溃之后发生了什么
重启时数据库要执行恢复(recovery):从最近一次检查点(checkpoint,可以理解成"已知一切正常的存档点")之后开始扫日志,把该重做的改动重做一遍,数据就回到了崩溃前最后一个"日志已落盘"的状态。
关键结论是:一条写入只要日志落了盘,就算成功。这也是为什么很多系统在向客户端返回"提交成功"之前,会等一次 fsync。等这一下,意味着下一秒断电,这笔数据也找得回来。
和几个近邻的区别
| 概念 | 记什么 | 频率 |
|---|---|---|
| WAL | 每次改动的增量,追加写 | 每次写入 |
| 快照 / 全量备份 | 某一刻的全部数据 | 定期 |
| 副本复制 | 发往其他节点的变更流 | 持续 |
WAL 管的是"最近几秒别丢",快照管的是"整份数据别丢",两者是配合关系:恢复时先还原快照,再把快照之后的 WAL 重放上去。另外,有些系统会单独维护一份逻辑日志用于主从复制,那是另一个用途,别和 WAL 混为一谈。
对从业者的实际意义
其一,"快"和"不丢"能同时成立,靠的就是它:把随机写换成顺序写,再把多次提交的落盘合并成一次(group commit),吞吐就上来了。
其二,它决定你能承诺什么。落盘频率通常是可调项:每次都等,最安全但慢;隔一小段时间刷一次,快,但崩溃时可能丢最近那一小段。选哪个,取决于业务能不能接受丢那几毫秒到几秒。具体参数名和默认值各家不同,以官方文档为准。
其三,它不只属于传统数据库。RocksDB、不少AI 词典:向量数据库">向量数据库和特征存储都用 WAL 保证写入不丢;训练任务保存检查点,也可以借用"先记账、再落盘"的思路。以后看到"保证不丢"这四个字,先问一句:日志在哪,什么时候刷盘。
