2016-10-19 27 views
1

我有一個OID生成一個顯然無效的元組。Postgres:`高速緩存查找失敗的約束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正在其他地方被引用。這些其他地方在哪裏,有誰知道我如何清理這樣的事情?

我真的喜歡上2831線

回答

4

我會說,這意味着你有目錄腐敗/* 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 

,使數據目錄的物理備份。這樣,如果您的救助操作進一步損壞了數據,您將擁有一份副本。