我们使用 Postgres 9.6,10+TB,多节点集群设置,由 Patroni 管理。WAL 档案和备份由本地工具管理pgrsync
。
archive_command
最初设置cp %p /archives/%f
为. 有一个后台作业 ( pgrsync
) 定期将档案推送到 S3。WAL 档案的容量更高(平均约为 200 个 WAL 文件/分钟,峰值为 500 个/分钟)。这cp
也增加了磁盘 IO 带宽,这对于我们在云环境中的我们来说非常宝贵。
我们正在寻求在应用程序中对此进行优化。另外,我注意到在pg_xlog
文件夹中有几个文件硬链接到其他 WAL 文件。(这部分没有完全理解,Postgres 内部怎么可能有一个 WAL 存档链接到另一个 - 这么多事务不太可能在一段时间后完全重复)。
无论如何,作为优化练习,我们将 设置archive_command
为ln %p /archives/%f
。这减少了磁盘 IO,我们只是在同一个文件中再添加一个链接。当我们完成复制到 S3 时,链接被删除并且操作系统管理删除实际文件,此时 Postgres 也释放它。在纸上看起来不错。除了一个问题:如果 Postgres 在完成后写入同一个文件(具有相同的 inode)archive_command
,那么我们就一团糟。请参考postgres:WAL 在在线备份结束之前结束,我们看到随机 WAL 损坏,我们不知道使用是否ln
导致了这种情况。
问题:使用ln
(hardlink) 代替cp
in是否安全archive_command
?
WAL 文件默认为 16MB。我们有增加它的计划,但我怀疑它会减少文件数量,但大小和 IO 可能会保持不变。不太可能有帮助,不是吗?
从备用节点备份 WAL 是一个好主意 - 或者用于归档的本土消费者。甚至干脆scp
到另一台服务器,以减少 Postgres 服务器上的磁盘写入 IO。由于任何东西都可以随时处于备用或主控状态,因此管理谁将实际推送文件可能会稍微复杂一些。所以,我要么去归档消费者,要么去scp
非 Postgres 服务器。
Reg 不pgrsync
直接调用,我们最初是这样做的。pgrsync
然后必须逐个处理每个文件(压缩并推送到 S3)。这降低了处理 500 个 WAL 文件(或 500*16MB WAL 字节)的能力。复制到另一个位置pgrsync
可以并行推送文件,因此可以每分钟处理 500 个 WAL 文件。我正在避免需要另一台服务器(rsync
/scp
到),但现在看起来这是一种更好的方法。
不,这不是一种选择,会导致麻烦。
第一个也是最明显的原因是 WAL 段只存在一次,即使在另一个目录中有指向它的硬链接。如果带有文件的磁盘发生任何事情,您将没有副本并且无法恢复。
第二个原因比较隐蔽,会导致数据损坏。当一个 WAL 段被归档并且比最新的检查点更旧时,它不一定被删除。如果 PostgreSQL 确定它需要新的 WAL 段(
max_wal_size
或者 - 在旧版本中 -checkpoint_segments
没有超出并且有很多数据修改活动正在进行),它将回收 WAL 段而不是删除它。如果发生这种情况,并且 PostgreSQL 在您设法将其复制到安全位置之前开始写入回收的 WAL 段,则原始 WAL 条目将被覆盖并丢失。如果您使用这样的 WAL 段进行恢复,PostgreSQL 会注意到 WAL 中有意外数据并停止恢复。