PostgreSQL 7.4 数据损坏

Dan*_*val 3 postgresql

我们正在处理以下情况(PG 版本为 7.4.30):不知何故,pg_database 中缺少一个数据库(psql \l 列表不再显示它)。更多,虽然您仍然可以 \c 到它,\d 表列表只显示表的一小部分。现有表上的 \d 也显示丢失的列。但是,所有表(仍然可见或不可见)都可以通过 psql 查询,结果集中的实际数据和列似乎很好。

我们备份了数据文件夹,并在过去 24 小时内尝试将情况恢复到 pg_dump 可以工作的程度。不幸的是,尽管我们在之前的类似帖子中尝试了大量建议,但我们还没有完全成功。Reindex 没有帮助,但是“VACUUM FULL FREEZE [ANALYZE]”确实释放了已用磁盘空间的 70%(14GB 到 4)。当然,数据库并没有像它应该的那样定期清空:

警告:某些数据库在超过 20 亿个事务中没有被清空详细信息:您可能已经遭受了事务环绕数据丢失。

没有冻结选项的完全真空确实使所有数据库、表和用户可见,但会重复,即 \l 然后显示数据库两次,数据库上的 \d 列出所有表两次。postgres 用户在 pg_user 等中出现两次。如果数据库未列出,pg_dump 将不起作用,如果 postgres 用户重复,则 pg_dump 将不起作用。

这对任何人来说听起来都很熟悉吗?遗憾的是,所有数据似乎都在那里,但我们无法将其恢复并还原到干净的数据库中。我们将不胜感激任何建议。

谢谢!

PS:我也在等待来自pgsql-admin邮件列表的反馈。

Chr*_*ers 5

首先,如果你还没有完成 vyegorov 建议的前两个,现在就去做。如果您已经吸尘,则不清楚在这种情况下您可能已经造成了什么样的损害。由于多次检查,在新版本的 PostgreSQL 上应该不会出现此错误,如果您之前升级过,则不会发生这种情况。我强烈建议将来尝试留在受支持的分支上。

我想花点时间描述一下可能导致问题的原因及其含义。IMO 的预后并不好,而且恢复数据(如果可能的话)可能既昂贵又耗时。我真诚地希望您在交易结束之前有一个良好的备份。如果没有,哎哟....

什么地方出了错

PostgreSQL 使用一种叫做 MVCC 的东西,这意味着旧版本的行会被保留下来,直到它们明显不再被使用。PostgreSQL 实践的 MVCC 用最小事务和最大事务标记每一行,并将它们用于可见性管理。当事务回滚时,那些输入的行不再可见,而删除的那些行仍然可见。交易 ID 是 32 位整数。

您应该定期清空 PostgreSQL 实例。这,除其他外,管理 MVCC 以便更少的事务 id 需要检查,管理表中的可用空间,并可以重置事务 id 序列。

当事务 ID 环绕时,会发生一些不好的事情,但它们归结为这样一个事实,即 PostgreSQL 无法再确定哪些行是可见的,哪些行是不可见的。请注意,这不仅适用于您自己表中的行,也适用于系统目录中的行。这是一件非常非常糟糕的事情。如果可以的话,最好的方法是在回绕发生之前从备份中恢复。这就是为什么数据库和表没有出现以及为什么吸尘完全复制它们的原因。

为什么升级会解决这个问题

现代版本的 PostgreSQL 自动启用了 autovacuum,它在后台运行真空进程以帮助防止此类问题。一旦环绕临近,更新的版本将拒绝为非超级用户启动新事务。这使您有机会在遭受可能的灾难性数据丢失之前检测并纠正问题。

PostgreSQL 7.4 已经近三年没有得到支持了。我不知道上一次清理任何东西是什么时候,但肯定是在数十亿次交易之前。这是不好的。