数据损坏
至关重要的首要响应
你认为你遇到了那些罕见但讨厌的索引或表损坏问题吗?
在做任何事情之前
立即停止 postmaster 并对你的数据库进行文件系统级别备份! 不要使用 pg_dump,而是将数据目录(包含 "base"、"pg_xlog"、"pg_clog" 等文件夹的目录)中的所有文件复制一份。
如果可能,将备份放到一个外部硬盘、DVD 或其他可以从你的电脑上断开的存储设备上,这样你就不会在备份后不小心修改了你的快照。
人们经常在尝试修复数据时破坏了可能恢复的数据。在尝试任何修复操作之前,请对数据库进行文件系统级别的备份。这可能可以拯救你的数据。
实验性的十六进制编辑器工具包 pg_hexedit 可以用于对 PostgreSQL 关系文件的低级分析。它只应该针对数据库的副本运行。
你的备份副本也是重要的证据,可以帮助找出导致问题的原因,让你能够防止它再次发生。修复工作通常会破坏这些证据。拥有损坏的数据可能是唯一能够找出它为什么损坏以及如何防止同样的情况再次发生的方法。
检测损坏
从 PostgreSQL 10 开始,有一个名为 amcheck 的扩展。虽然它只验证 B-Tree 索引的完整性,但它非常适合用作通用损坏烟雾测试,特别是因为可以使用 "heapallindexed" 验证选项(仅限更高版本)将索引与堆进行验证。请注意,还有一个针对早期 PostgreSQL 版本的 GitHub 上的版本。
PostgreSQL 9.6 引入了一个 更专业的工具来验证可见性映射的完整性,称为 pg_visibility。这在怀疑可见性映射损坏的情况下可能特别有用。
PostgreSQL 12 及更高版本具有进行 pg_checksums 的能力。这些会原位重写数据库文件。有一个 设置它们的教程。
原因
记住,大多数损坏都是由硬件问题引起的
- 具有故障/磨损的电池备份的 RAID 控制器,以及意外的电源故障
- 启用了写回缓存的硬盘驱动器,以及意外的电源故障
- 具有不足的电源故障保护的廉价 SSD,以及意外的电源故障
- 有缺陷的 RAM
- 有缺陷或过热的 CPU
其他原因可能是
- 通过 pg_basebackup 或流式复制迁移到较新的操作系统 其中源机器和目标机器运行不同的 glibc 版本。常见的边界是 CentOS 7 --> CentOS 8 和 Ubuntu 18.04 --> Ubuntu 20.04,但损坏可能发生在任何 底层 c 库更改影响 LOCALE 排序规则 的地方。
- 配置了以下内容的数据库系统fsync=off以及操作系统崩溃或电源故障
- 配置为使用写入屏障,以及忽略写入屏障的存储层。 LVM 是一个特殊的罪魁祸首,但 Liunx 2.6.33-rc1 添加了完整的屏障支持。
- PostgreSQL 错误
- 操作系统错误
- 管理员错误
- 直接修改 Postgres 数据目录内容
- 有缺陷的故障转移过程,例如rsync'ing 没有pg_start_backup
- 以及更多
下一步做什么?
考虑联系 专业的支持服务提供商。损坏问题可能很耗时且难以诊断和修复,而且通常与硬件或配置相关。
阅读 报告问题的指南 并将有关该问题的信 息发布到 pgsql-general 邮件列表。请记住,你的硬件设置和 postgresql 配置是重要的信息,错误消息、Pg 版本等也是如此。
Christophe Pettus 关于数据库损坏的 FOSDEM 演示 也值得一读,但你不会听到它带来的口头警告。特别地,那里描述的恢复技术用于从数据库中恢复你所能恢复的内容,并理解你会丢失数据块,不一致的 FK 关系,重新出现的已删除行/可见的未提交行,以及所有各种问题,具体取决于所使用的修复技术。它假设你已经完成了明智的初步调查并修复了可能导致问题的任何不太严重的错误。