Postgres:`约束34055`的缓存查找失败

时间:2016-10-19 07:38:46

标签: postgresql constraints oid

我有一个正在生成显然无效的元组的OID。

这是在尝试在某些\set VERBOSITY verbose之后删除psql中的表时出现的错误:

delete from my_table where my_column = 'some_value';
ERROR:  XX000: cache lookup failed for constraint 34055
LOCATION:  ri_LoadConstraintInfo, ri_triggers.c:2832

这是我发现的elsewhere

2827             :     /*
2828             :      * Fetch the pg_constraint row so we can fill in the entry.
2829             :      */
2830         548 :     tup = SearchSysCache1(CONSTROID, ObjectIdGetDatum(constraintOid));
2831         548 :     if (!HeapTupleIsValid(tup)) /* should not happen */
2832           0 :         elog(ERROR, "cache lookup failed for constraint %u", constraintOid);
2833         548 :     conForm = (Form_pg_constraint) GETSTRUCT(tup);
2834             : 
2835         548 :     if (conForm->contype != CONSTRAINT_FOREIGN) /* should not happen */
2836           0 :         elog(ERROR, "constraint %u is not a foreign key constraint",

我读到这意味着OID正在其他地方被引用。这些其他地方在哪里,有谁知道如何清理这样的东西?

我非常喜欢第2831行的/* should not happen */评论。

1 个答案:

答案 0 :(得分:4)

我想说这意味着您有目录损坏。

外键约束在内部实现为触发器。当触发器触发时,它会尝试查找属于它的约束。在您的情况下,这似乎失败了,这会导致错误。

你可以亲眼看看:

SELECT tgtype, tgisinternal, tgconstraint
   FROM pg_trigger
   WHERE tgrelid = 'my_table'::regclass;

┌────────┬──────────────┬──────────────┐
│ tgtype │ tgisinternal │ tgconstraint │
├────────┼──────────────┼──────────────┤
│      5 │ t            │        34055 │
│     17 │ t            │        34055 │
└────────┴──────────────┴──────────────┘
(2 rows)

现在尝试查找该约束:

SELECT conname
   FROM pg_constraint
   WHERE oid = 34055;

┌─────────┐
│ conname │
├─────────┤
└─────────┘
(0 rows)

要从这种损坏中恢复,您应该恢复最新的良好备份。

您可以尝试使用pg_dumpall转储正在运行的PostgreSQL集群,创建新集群并在那里恢复转储来抢救您的数据。如果你很幸运,你现在拥有一个很好的集群副本,你可以使用它。如果转储或还原由于数据不一致而失败,则必须使用更高级的方法。

与数据损坏一样,最好先使用

停止群集
pg_ctl stop -m immediate

并对数据目录进行物理备份。这样,如果你的打捞操作进一步损坏数据,你就有一份副本。