2016-10-19 18 views
1

У меня есть OID, который генерирует кортеж, который, очевидно, недействителен.Postgres: `cache lookup failed for constraint 34055`

Это ошибка я получаю при попытке удалить таблицу в PSQL после некоторого \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 ссылается в других местах. Где эти другие места, и кто-нибудь знает, как я чистить что-то подобное?

мне очень нравится /* should not happen */ комментарий по линии 2831

ответ

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 

и сделать физическую резервную копию данных каталога. Таким образом, у вас есть копия, если ваша операция по спасению еще больше повредит данные.