pgsql.cc 提供对 postgresql.org 官网内容的中文翻译,由 Pigsty 团队维护。
本章说明如何使用预写式日志,实现高效、可靠的运行。
可靠性是任何严肃数据库系统的重要属性,而 PostgreSQL 会尽一切可能保证运行可靠。可靠运行的 一个方面是,已提交事务所记录的所有数据都应存储在不受断电、操作系统故障和 硬件故障影响的非易失性区域中(当然不包括该非易失性区域本身的故障)。通常,只要 能成功将数据写入计算机的永久存储设备(磁盘驱动器或等效设备),就满足这一 要求。实际上,即使一台计算机遭受致命损坏,只要磁盘驱动器得以幸存,就可以将 它们移到另一台硬件相近的计算机上,所有已提交事务仍将完好无损。
虽然周期性地强制将数据写到磁盘盘片似乎是个简单操作,但事实并非如此。由于 磁盘驱动器远慢于主存和 CPU,在计算机主存与磁盘盘片之间存在多层缓存。首先是 操作系统的缓冲区缓存,它会缓存常用磁盘块并合并磁盘写入。幸运的是,所有 操作系统都为应用提供了强制将数据从缓冲区缓存写入磁盘的方法,而 PostgreSQL 会使用这些机制。(关于如何调整这一 过程,见参数 wal_sync_method。)
其次,磁盘驱动器控制器中可能还有缓存;这在 RAID 控制卡上 尤为常见。其中一些缓存是 直写式,也就是说写请求一到达 就立刻传递给驱动器。另一些是 回写式,也就是说数据会在 稍后的某个时间发送到驱动器。这类缓存可能构成可靠性隐患,因为磁盘控制器缓存 中的内存是易失性的,断电时会丢失内容。较好的控制卡配有 电池后备缓存,也就是卡上 带有电池,可在系统断电时维持缓存供电。电力恢复后,数据便会写入磁盘驱动器。
最后,大多数磁盘驱动器自身也带有缓存。有些是直写式,有些是回写式;对于 回写式驱动器缓存,同样存在与磁盘控制器缓存相同的数据丢失隐患。消费级 IDE 和 SATA 驱动器尤其可能带有在断电后无法保留内容的回写式缓存。要在 Linux 上检查写缓存,可使用 hdparm -I; 如果 Write cache 旁边有 *,则说明已启用。 用 hdparm -W 可关闭写缓存。在 FreeBSD 上使用 atacontrol。(SCSI 磁盘可用 sdparm 关闭 WCE。)在 Solaris 上,磁盘写缓存由 format -e 控制。(Solaris 的 ZFS 文件系统在启用磁盘写缓存时是安全的, 因为它自己会发出磁盘缓存刷新命令。)在 Windows 上,如果 wal_sync_method 为 open_datasync(默认值), 可通过取消勾选 我的电脑\打开\{选择磁盘驱动器}\属性\硬件\属性\策略\启用磁盘上的写缓存 来禁用写缓存。同样在 Windows 上,fsync 和 fsync_writethrough 从不使用写缓存。fsync_writethrough 选项也可用于在 MacOS X 上禁用写缓存。
当操作系统向存储硬件发出写请求后,它几乎做不了什么来确保数据已经到达真正的非易失性存储区域。相反,管理员有责任确保所有存储组件都能保证数据完整性。应避免使用写缓存没有电池后备的磁盘控制器。在驱动器层面,如果驱动器无法保证在关闭前把数据写出,就应禁用回写缓存。
数据丢失的另一种风险来自磁盘盘片写操作本身。磁盘盘片被分为若干扇区,通常每个 512 字节。每一次物理读写都处理整个扇区。当写请求到达驱动器时,它可能是 512 字节、 1024 字节或 8192 字节,而写入过程可能在任何时刻因断电失败,这就意味着 某些 512 字节扇区写成功了,另一些却没有。为防范这类故障, PostgreSQL 会在修改磁盘上的实际页面 之前,定期将整页镜像写入持久 WAL 存储。这样一来,在 崩溃恢复时 PostgreSQL 就能从 WAL 恢复部分写入的 页面。如果你使用了带后备电池的磁盘控制器,或者能阻止部分页面写入的文件系统 软件(如 ReiserFS 4),可以通过关闭参数 full_page_writes 来禁用这种页面镜像。
译文有误、术语不当或页面显示问题,请到译文仓库 pgsty/pgdoc 报告译文问题。 英文原文本身的问题,请在当前版本的对应页面向上游反馈;上游不再修订已结束维护的版本。