9.3. WAL 配置

有几个与 WAL 相关的参数会影响数据库性能. 本节讨论它们的使用.参阅 Section 3.4 获取配置参数的细节.

有两个常用的 WAL 函数: LogInsertLogFlushLogInsert 用于向共享内存中的 WAL 缓冲区里加一条新的记录.如果没有空间存放 新记录,那么LogInsert 就不得不写出 (向内核缓存里写)一些填满了的WAL缓冲. 我们可不想这样,因为 LogInsert 用于 每次数据库低层修改(比如,记录插入),都要花在受影响的数据页 上持有一个排它锁的时间,并且认为该操作越快越好;更糟糕的是, 写 WAL 缓冲可能还会导致创建新的日志段, 它花的时间甚至更多.通常,WAL 缓冲区应该由 一个 LogFlush 请求来写和冲刷, 在大部分时候它都是发生在事务提交的时候以确保事务记录被冲刷到 永久存储器上去了.在那些日志输入量比较大的系统上, LogFlush 请求可能不够频繁,这样就不能避免 WAL 缓冲区被 LogInsert 写.在这样的系统上,我们应该通过修改 WAL_BUFFERS 参数的值来增加 WAL 缓冲区的数量.缺省的 WAL 缓冲区数量是 8. 增加这个数值将影响共享内存的使用.

检查点(Checkpoints)是事务的顺序的点, 我们保证在该点之前的所有日志信息都更新到数据文件中去了. 在检查点时,所有脏数据页都冲刷到磁盘并且向日志文件中写入一条 特殊的检查点记录.结果是,在发生崩溃的时候,恢复器就知道 应该从日志中的哪条记录(称做 redo 记录)开始做 REDO 操作, 因为在该记录前的对数据文件的任何修改都已经在磁盘上了. 在完成检查点处理之后,所有在 redo 记录之前的日志段都被删除, 因此检查点用于释放在 WAL 目录里面的磁盘空间. (在实现了基于 WALBAR 之后,日志段可能就是归档,而不是删除.) 检查点处理器也可以创建几个日志段为将来使用,这样就避免了 LogInsertLogFlush 花时间创建它们.

WAL 日志在磁盘上是以一个 16 MB 的文件集保存的, 这些文件叫段(segments). 缺省时,只有在当前段里超过 75% 的空间被使用了之后才创建新的段. 但是我们可以命令服务器在检查点时创建多达 64 个日志段, 方法是修改 WAL_FILES 配置参数.

为了获取更快的崩溃后恢复,我们最好更频繁一些创建检查点. 但是,我们应该在更多检查点和冲刷脏数据页之间取得平衡; 另外,为了保证数据页的完整,在每个检查点后的第一个数据页的修改 都会导致记录整个数据页的内容,因此也增加了向日志的输出和日志的尺寸.

postmaster 每隔一段时间就 排生一个特殊的进程以创建下一个检查点. 每隔 CHECKPOINT_SEGMENTS 个日志段就创建一个检查点, 或者每隔� CHECKPOINT_TIMEOUT 秒创建一个. 以先到为准.缺省设置分别是 3 个段和 300 秒. 我们也可以用 SQL 命令 CHECKPOINT 强制一个检查点.

COMMIT_DELAY 定义了后端在使用 LogInsert 向日志中写了一条已提交 的记录之后,在执行一次 LogFlush 之前休眠 的毫秒数.这样的延迟可以允许其它的后端把它们提交的记录追加 到日志中,这样就可以用一次日志同步把所有日志冲刷到日志中. 如果没有打开 fsync 或者当前少于 COMMIT_SIBLINGS 个其它后端处于活跃事务状态的时候则不会发生休眠; 这样就避免了在其它事务一时半会不会提交的情况下睡眠. 请注意在大多数平台上,休眠要求的分辩率是十毫秒, 所以任何介于 1 和 10000 微秒之间的非零 COMMIT_DELAY 的作用都是一样的.

WAL_SYNC_METHOD 参数决定 Postgres 如何 请求内核强制将 WAL 更新输出到磁盘.只要满足可靠性,那么 所有选项应该都是一样的,但是哪个最快则可能和平台密切相关. 请注意如果你关闭了 FSYNC,那么这个参数 就无所谓了.

WAL_DEBUG 参数设置为任何非零值都会导致 每次 LogInsertLogFlush WAL 调用都被记录到标准错误.目前,这个非零值是多少 没有什么区别.这个选项以后可能会被更通用的机制取代.