29.5. WAL内部

WAL 是自动打开的。除了要求一些磁盘空间存放 WAL 日志以及一些必要的调节以外(参阅Section 29.4),对管理员没有什么其它要求。

WAL 日志存放在数据目录的pg_xlog子目录里, 它是作为一个文件段的集合存储的,通常每段 16MB (但在建立服务器时大小可以通过改变的 --with-wal-segsize配置选项)。每个段分为网页,通常每8 KB(这个大小是可以改变的, 通过的--with-wal-blocksize配置选项)。日志记录头在access/xlog.h 里描述;日志内容取决于它记录的事件类型。段文件的名字是递增自然数,从 000000010000000000000000开始。目前这些数字不能循环使用, 不过要把所有可用的数字都用光也需要非常长的时间。

日志位于和主数据库文件不同的另外一个磁盘上会比较好。你可以通过把pg_xlog 目录移动到另外一个位置(此时必须关闭服务器),然后在原来的位置创建一个指向新位置的符号链接。

WAL 的目的是确保在数据库记录被修改之前先写日志, 但是这个目的有可能被那些向内核谎报成功写入的磁盘驱动器破坏, 这时候,它们实际上只是缓冲了数据而并未把数据存储到磁盘上。 这种情况下的电源失效仍然可能导致不可恢复的数据崩溃; 管理员应该确保保存PostgreSQL日志文件的磁盘不会做这种虚假汇报。 (查阅Section 29.1)。

在完成一个检查点并且刷新了日志文件之后,检查点的位置就保存在 了pg_control文件里。因此在开始做恢复的时候, 后端首先读取pg_control和检查点记录; 然后通过从检查点记录里标识的日志位置开始向前扫描执行 REDO 操作。 因为数据页的所有内容都保存在检查点之后的第一个页面修改的日志里 (假设full_page_writes没有被禁用), 所以自检查点以来的所有变化都将被恢复到一个一致的状态。

但是为了处理pg_control可能的损坏, 我们实际上应该实现对现存日志段的反向读取顺序(从最新到最老), 这样才能找到最后的检查点。这些还没有实现。pg_control 很小(比一个磁盘页小),因此它出现只写了一部分的问题的概率几乎为零, 到目前为止,我们还没有看到不能读取 pg_control 自身的错误。 因此,尽管这在理论上是一个薄弱环节,但是实践中 pg_control 似乎并不会出现问题。