Postgres:`约束 34055 的缓存查找失败`
Postgres: `cache lookup failed for constraint 34055`
我有一个 OID 正在生成一个显然无效的元组。
这是我在 \set VERBOSITY verbose
:
之后尝试在 psql 中删除 table 时遇到的错误
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 */
评论。
我会说这意味着你有目录损坏。
外键约束在内部实现为触发器。当该触发器触发时,它会尝试找到属于它的约束。这在你的情况下似乎失败了,这会导致错误。
你可以自己看看:
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
并对数据目录进行物理备份。这样,如果您的抢救操作进一步损坏了数据,您就有了一份副本。
我有一个 OID 正在生成一个显然无效的元组。
这是我在 \set VERBOSITY verbose
:
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 */
评论。
我会说这意味着你有目录损坏。
外键约束在内部实现为触发器。当该触发器触发时,它会尝试找到属于它的约束。这在你的情况下似乎失败了,这会导致错误。
你可以自己看看:
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
并对数据目录进行物理备份。这样,如果您的抢救操作进一步损坏了数据,您就有了一份副本。