PostgreSQL 无备份恢复:2.5 TB 集群案例研究
一个来自 Postgres Professional 的 2.5 TB PostgreSQL 集群在虚拟机上运行了三年,却没有备份。磁盘配置未预留空间,超过了主机的物理大小,通过写时复制扩展。包括 1C 在内的十个活跃数据库在加载新信息库后崩溃:WAL 日志填满了管理程序磁盘,检查点无法完成。
管理员手动删除了 WAL 文件并尝试在快速模式下停止 postmaster,但未成功。强制 SIGKILL 停止导致因巨大的 shared_buffers 而出现数据损坏。通过 pg_resetwal 启动禁用了 WAL 恢复;简单查询可行,但复杂查询无效。
诊断与初步补丁
通过 SIGRTMIN+6 信号使用 crash_info 实用程序(可在免费的 Postgres Professional 版本中找到),我们识别出系统目录的 btree 索引中 _bt_moveright 挂起。我们启用了 ignore_system_indexes 参数或应用补丁以绕过系统索引。REINDEX SYSTEM 过夜未完成。
pg_dump 在检索表列表时挂起,因为缺少索引。--data-only 参数无济于事:实用程序请求扩展统计信息。pg_dump 的补丁排除了对系统目录的不必要查询。
数据导出与后果
24 小时后,关键数据库的数据导出到了新集群。向 PostgreSQL 社区提交的错误报告及补丁(针对 13-17 版本)突出了 pg_dump 在损坏索引方面的问题。社区拒绝将其归类为错误:无备份恢复不是优先事项。
客户购买了 Postgres Professional 的企业支持。pg_dump 的替代方案是通过 1C 的表列表进行 COPY(数据库中有 50,000 个表),由脚本生成而不访问系统目录。
管理员的关键错误
- 缺乏备份和副本。
- 手动删除 WAL 日志。
- 使用 SIGKILL 而不是 SIGQUIT 停止 postmaster。
- 忽略磁盘预留建议。
- 依赖未验证备份的“指南”。
- 未考虑目录损坏而错误选择 pg_dump。
关键要点
- 没有备份(转储、副本),无法完全恢复 2.5 TB 集群。
- ignore_system_indexes 允许绕过损坏的系统索引。
- crash_info 可用于无控制台访问的状态转储。
- pg_dump 易受目录损坏影响:使用 --data-only 配合补丁或 COPY。
- 当 shared_buffers 较大时,SIGKILL postmaster 会破坏数据。
给 DBA 的教训
1C 集群需要 WAL 清理、磁盘空间监控和复制。巨大的 shared_buffers 会掩盖问题直至灾难发生。对于 50,000 个表,从 1C 元数据生成 COPY 脚本。
— Editorial Team
暂无评论。