29.2. 预写式日志(WAL)

预写式日志(WAL)是一种确保数据完整性的标准方法。 有关它的详细描述可以在大多数(如果不是全部的话)有关事务处理的书中找到。简而言之, WAL的中心思想是对数据文件的修改(它们是表和索引的载体) 必须只能发生在这些修改已经记录到日志之后,也就是说, 在描述这些变化的日志记录刷写到永久存储器之后。如果我们遵循这个过程, 那么就不需要在每次事务提交的时候都把数据页刷写到磁盘, 因为在出现崩溃的情况下可以用日志来恢复数据库: 任何尚未应用于数据页的修改都可以先从日志记录中重做(这叫向前滚动恢复,也叫 REDO)。

提示: 因为WAL在崩溃之后恢复数据文件内容, 所以日志文件系统对于数据文件或WAL文件的可靠存储是完全没有必要的。实际上, 日志开销会降低性能,尤其是如果日志导致文件系统数据 刷写到磁盘,幸运的是,在记录日志期间的数据刷写通常可以通过一个文件系统的挂载选项禁用, 例如,在Linux ext3文件系统上的data=writeback。在崩溃后日志文件系统确实提高了启动速度。

使用WAL显著地减少了磁盘写的次数,因为只有日志文件需要刷写到磁盘以保证事务被提交, 而不是事务修改的所有数据文件都需要刷写到磁盘。日志文件是顺序写的,所以同步日志的开销要远比刷写数据页的开销小。 尤其对于有很多修改不同数据存储位置的小事务的服务而言更是如此。另外,当服务器正在处理许多小的并发事务时, 日志文件的一个fsync足以提交许多事务。

WAL还提供了数据库在线备份和基于时间点恢复的可能,就像第 24.3 节 里描述的那样。通过归档的 WAL 文件,可以将数据库恢复到 WAL 文件包含的任意时刻: 只需要简单地安装以前的数据库物理备份,然后重做 WAL 到希望的时间点。另外, 物理备份不必是数据库状态的一个即时快照;如果其制作花了较长的时间周期, 对于该周期内WAL日志的重做将修复任何内部的不一致。