database - PostgreSQL 8.3.11 已锁定;孤立的 pg_toast 数据库对象恢复

标签 database postgresql psql vacuum

你好 Slack Overflowvians。

所以我遇到了这个运行 8.3.11 的 PostgreSQL 服务器(是的,我知道),它处于锁定状态:

ERROR:  database is not accepting commands to avoid wraparound data loss in database "postgres"
HINT:  Stop the postmaster and use a standalone backend to vacuum that database.

通常自动真空守护进程 (autovacuum=on) 会处理这个,但是因为下面的四个 TOAST(允许存储大字段值 8 kB 切片,如面包),数据库对象。但是由于这些损坏的数据库对象,此数据库的 XID 从未被重置。

以下是使用管理员用户在单用户模式下运行服务器时的输出片段:

SELECT oid, relname, age(relfrozenxid) FROM pg_class WHERE relkind = 't' ORDER BY age(relfrozenxid) DESC LIMIT 4;


    ----
     1: oid = "2421459"     (typeid = 26, len = 4, typmod = -1, byval = t)
     2: relname = "pg_toast_2421456"        (typeid = 19, len = 64, typmod = -1, byval = f)
     3: age = "2146484084"  (typeid = 23, len = 4, typmod = -1, byval = t)
    ----
     1: oid = "2421450"     (typeid = 26, len = 4, typmod = -1, byval = t)
     2: relname = "pg_toast_2421447"        (typeid = 19, len = 64, typmod = -1, byval = f)
     3: age = "2146484084"  (typeid = 23, len = 4, typmod = -1, byval = t)
    ----
     1: oid = "2421435"     (typeid = 26, len = 4, typmod = -1, byval = t)
     2: relname = "pg_toast_2421432"        (typeid = 19, len = 64, typmod = -1, byval = f)
     3: age = "2146484084"  (typeid = 23, len = 4, typmod = -1, byval = t)
    ----
     1: oid = "2421426"     (typeid = 26, len = 4, typmod = -1, byval = t)
     2: relname = "pg_toast_2421423"        (typeid = 19, len = 64, typmod = -1, byval = f)
     3: age = "2146484084"  (typeid = 23, len = 4, typmod = -1, byval = t)

请注意,此服务器上的年龄远高于 vacuum_freeze_min_age(在成功 VACUUM 后设置的值),这也是它发出上述原始错误的原因。以上是在运行 VACUUM FULL 之后;所有其他表都很好。

SELECT relfilenode FROM pg_class WHERE oid=2421459;

因此,当我们查看磁盘时(使用上面每个表的 pg_class.relfilenode 值),toast 表的文件丢失了:

$ find /var/lib/pgsql/data/ -type f -name '2421426' | wc -l  # Bad toast
0

当我们在磁盘上查看 toast 的索引时

 SELECT relfilenode FROM pg_class WHERE (select reltoastidxid FROM pg_class WHERE oid=2421459)

$ find /var/lib/pgsql/data/ -type f -name '2421459' | wc -l  # Bad toast's index
0

然后我们试图找到与坏 toast 记录相关的表:

SELECT * FROM pg_class WHERE reltoastrelid=2421459;

以上各表均有 0 个结果! VACUUM 命令没有用于重置这些关系的 XID 的表。

当我们检查 pg_depend 表并发现这些 TOAST 表没有引用时:

SELECT * FROM pg_depend WHERE refobjid IN(2421459,2421450,2421435,2421426)

问题

  1. 你能从数据库中删除坏的 TOAST 表和 TOAST 表索引吗? pg_class 表(例如 DELETE FROM pg_class where oid=2421459)
  2. 还有我们还需要删除关系的其他表吗 来自?
  3. 我们能否创建一个临时表并将其链接到 TOAST 的 索引的 oid?

上面 #3 的示例:

CREATE TABLE adoptedparent (colnameblah char(1));
UPDATE pg_class SET reltoastrelid=2421459 WHERE relname='adoptedparent';  
VACUUM FULL VERBOSE adoptedparent

编辑:

select txid_current() 是 3094769499 所以这些表在很久以前就已经损坏了。我们不需要恢复数据。我们在 Linux 2.6.18-238.el5 上运行 ext4 文件系统。我们检查了相关的 lost+found/ 目录,文件不在那里。

最佳答案

仅针对家庭观众,在这种特殊情况下,决议是直接编辑 pg_class。当然,还要将服务器更新为受支持的 Postgres 版本!

具体答案:

  1. 是的,您可以,尽管在大多数情况下最好创建一个空表,将 toast 关系附加到该表,添加 pg_depend 条目,然后删除该表。在这种情况下,这没有意义,因为确实没有其他对象依赖于这些 toast 表。

    1. 通常 toast 表在 pg_index 中也有索引,在 pg_depend 中有条目。这些没有。

    2. 见上文。

关于database - PostgreSQL 8.3.11 已锁定;孤立的 pg_toast 数据库对象恢复,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32874198/

相关文章:

mysql - MySQL 回滚失败

mysql - 使用 MySQL 将度/分/秒转换为小数

entity-framework - 用于 postgresql 和 ado.net 实体数据模型的 MultipleActiveResultSets

ruby-on-rails - 急切加载多态关联的第一条记录

sql - 通过不正确分组来创建带有组的 View

database - 在数据库中找到重复地址,阻止用户提前输入?

mysql - 数据库数据标准化?

Win32 : postgres password 中的 PostgreSql

exception-handling - 捕获所有错误 psql 函数异常

postgresql - 使用 psql 登录