什么是WAL机制?
WAL(Write-Ahead Logging,预写日志)是一种保证数据库操作原子性和持久性的核心机制。其核心原则可概括为:
任何数据修改操作,必须在对应的日志记录持久化到磁盘之后,才能将实际数据写入磁盘。
理论基石
-
持久化顺序性:日志的写入必须早于数据修改的完成。
-
操作可重放性:所有修改操作都能通过日志完整重建。
-
故障可恢复性:系统崩溃后,通过日志可恢复到一致状态。
为什么需要WAL机制?
1. 传统数据写入的缺陷
假设直接修改数据页(无WAL):
-
崩溃不一致:若在写入数据页过程中发生崩溃,数据可能处于“半完成”状态。
-
无法回滚:已部分写入的数据难以追踪和撤销。
-
随机写性能差:频繁修改分散的数据页会导致磁盘寻道开销。
2. WAL的理论优势
维度 | 无WAL | 有WAL |
---|---|---|
原子性 | 无法保证 | 通过日志回滚保证 |
持久性 | 依赖即时刷盘 | 日志持久化即视为操作完成 |
性能 | 随机写效率低 | 顺序追加日志提升吞吐量 |
恢复能力 | 数据可能损坏 | 通过日志重建一致状态 |
WAL的核心理论组件
1. 日志记录(Log Record)
每条日志记录需包含足够信息以支持恢复,通常包括:
-
事务ID(XID):标识操作所属事务。
-
操作类型:如插入(INSERT)、更新(UPDATE)、提交(COMMIT)等。
-
修改内容:
-
逻辑日志:记录操作语义(如“账户A增加100元”)。
-
物理日志:记录数据页的具体修改(如“页面P偏移量O处写入字节B”)。
-
-
LSN(Log Sequence Number):全局唯一的日志序列号,标识操作顺序。
2. 检查点(Checkpoint)
-
作用:定期记录数据库的全局一致状态,限制恢复时需要处理的日志范围。
-
类型:
-
模糊检查点:允许检查点期间存在未完成事务。
-
精确检查点:冻结所有事务后记录一致状态。
-
WAL如何保证ACID特性?
1. 原子性(Atomicity)
-
提交原子性:事务的所有操作日志持久化后,才标记为“已提交”。
-
回滚机制:通过反向扫描日志,执行补偿操作(UNDO)回滚未提交事务。
2. 持久性(Durability)
-
日志优先持久化:事务提交前,其所有日志记录必须强制刷盘(
fsync
)。 -
数据页延迟写入:允许数据页在内存中缓存,通过后台线程异步刷盘。
3. 隔离性与一致性
-
日志与锁的结合:通过锁机制保证事务隔离,日志记录锁操作。
-
逻辑约束:在日志中记录完整性约束验证结果。
崩溃恢复
-
分析阶段(Analysis):
确定崩溃时活跃的事务集合,以及需要重做(REDO)和回滚(UNDO)的日志范围。 -
重做阶段(REDO):
从最早的未完成操作开始,按顺序重新执行所有已提交事务的操作。 -
回滚阶段(UNDO):
逆序撤销所有未提交事务的操作。