PostgreSQL 18 中文参考文档(未翻译部分保留英文)🌐 切换到英文原版 →

28.1. 可靠性 #

可靠性是任何工业级企业数据库系统的核心生命线,PostgreSQL 竭尽所能保障系统运行的绝对可靠。可靠性的一个关键基石在于:已提交事务记录的所有数据,必须被安全固化在掉电非易失的存储介质上,使其免受意外停电、操作系统崩溃乃至宿主物理机硬件故障的损害(当然存储介质本身的物理毁损除外)。成功将数据刷入计算机的持久化存储设备(固态硬盘、机械硬盘或等效介质)通常能够满足这一严苛要求。事实上,即使主机遭遇致命物理损毁,只要磁盘物理完好,将其挂载到具有类似硬件的备用机器上,所有已提交的事务都将完整无损地恢复重建。

虽然定期将数据物理写入磁盘盘片看似只是一个简单的 I/O 操作,但工程实现上远非如此。因为外部磁盘设备相对于高速主存和 CPU 而言极其缓慢,在计算机的主存与物理盘片之间天然存在数层各级硬件与系统缓存。 首先是操作系统的页缓存(Page Cache),它负责暂存高频读取的数据块并合并物理写操作。幸运的是,主流操作系统均向应用程序提供了强制将缓冲区数据同步落盘的系统调用接口,PostgreSQL 深度依赖这些接口(详见 wal_sync_method 参数)。

其次,在外部磁盘控制器卡(尤其是企业级硬件 RAID 卡)上往往配备有专用的板载缓存。这些缓存有的被配置为直写(write-through,数据一到达控制器卡立刻物理写入底层磁盘);有的则被配置为回写(write-back,数据暂存在易失缓存中并在稍后延时刷盘)。回写式控制器缓存在可靠性上构成了潜在的致命隐患,因为控制器板载内存在遇到突发停电时会瞬间丢失内容。高规格的企业级控制器卡通常搭载有电池后备单元(BBU)或超级电容,能在突发掉电时维持板载缓存供电数天,待系统电力恢复后自动将暂存数据刷写到磁盘中。

最后,绝大多数磁盘硬盘本身也自带板载缓存。消费级的 SATA 机械硬盘和部分消费级固态硬盘(SSD)往往默认开启易失性的回写缓存,在突发掉电时根本无法保证未落盘数据的存活。

在生产环境中通常建议由管理员主动关闭磁盘内部不受保护的写缓存:

现代硬盘提供了硬件缓存强制冲刷指令(例如 SATA 的 FLUSH CACHE EXT 以及 SCSI 的 SYNCHRONIZE CACHE)。部分高级文件系统(如 ext4、XFS 与 ZFS)能够利用这些指令在底层调度数据刷盘。开发者可以通过运行官方工具 pg_test_fsync 真实压测当前操作系统和存储子系统的实际 fsync 吞吐能力与时延特征。

数据丢失的另一个物理风险来自于磁盘盘片的块写入操作本身。磁盘按扇区(通常为 512 字节或 4096 字节)进行读写,而 PostgreSQL 的内存数据页通常是以 8192 字节(即 16 个 512 字节扇区)为一个逻辑读写单元。在物理写入 8KB 数据块的中途如果遭遇突发停电,极易导致部分扇区写入成功而其余扇区未写入,从而破坏整个数据页产生半写裂页(torn page)。为防范此类物理损坏,PostgreSQL 在每个检查点之后、首次修改某个数据页时,会强制将该数据页的全页镜像(Full Page Image)完整记录在持久化的 WAL 日志中。如此一来,在系统崩溃重启恢复时,如果检测到磁盘数据页损坏,可以通过回放 WAL 中的全页镜像进行物理修复(该行为由参数 full_page_writes 控制)。

此外,PostgreSQL 还构筑了全方位的硬件静默数据损坏防护体系: