追踪“无法打开与OID的关系”错误的原因

时间:2011-02-17 15:10:35

标签: postgresql

最近我的PostgreSQL 8.2.4记录了这样的错误:

ERROR:  could not open relation with OID nnnnnnnnn
CONTEXT: SELECT a,b,c FROM table_C

错误总是由相同的场景引起:对表A的更新导致触发器触发,该触发器将数据插入到表B中,这触发另一个触发器,其中(在许多其他事情中)在表C上进行选择。然后将表C报告为上述问题的上下文。导致出现错误消息的查询序列每天都会执行,并且每天都会抱怨缺少相同的OID。

查询pg_class时,错误消息中提到的OID很自然。执行有问题的SQL(即,在表C上选择)不会导致任何问题。我试图找出所涉及的所有表之间的OID和连接,以找出对不存在的OID的引用的位置,但我失败了。我从表A开始并得到它的OID(pg_class.reltype)并验证它已附加触发器。当我使用pg_trigger.tgrelid = pg_class.reltype作为条件查询pg_trigger时,问题就开始了。查询大喊0行,但是当我只通过relname / tgname查询表时,我得到不同的OID,就像触发器在不同的表上一样。我做了一个快速测试,看来,创建一个带有触发器的简单表会产生相同的结果。

所以我的问题是:

  1. 当我可以在pg_class中找到表时,如何导航pg_trigger(以及其他pg表,如pg_attribute,pg_shdepend)表?

  2. 如果我设法找到有问题的OID的引用,我可以通过在pg_class表上直接更新/删除来简单地删除引用吗?

3 个答案:

答案 0 :(得分:4)

请注意,'reltype'是表的rowtype的OID - 表本身的OID是pg_class.oid(这是一个系统列,因此不会显示在\d或{{ 1}}输出,你需要明确选择它。

希望这将解决目录表如何相互关联的一些谜团!使用oid作为主键,在相当多的其他表中重复相同的模式。

这看起来是一个非常严重的问题,可能表明存在某种目录损坏?您可以直接修改select *等,但显然这样做有一些风险。我不能想到在这里给出很多通用的建议 - 根据你找到的东西,做什么会有很大差异。

答案 1 :(得分:0)

如果在SQL函数中执行语句时出现这种情况,则将语言从SQL更改为plpgsql。原因可以是缓存计划。 plpgsql函数在运行之间使计划无效,而sql函数似乎跳过此步骤。

答案 2 :(得分:0)

在后端验证表,PostgreSQL为创建的每个表分配唯一的 OID

尝试在数据库端插入数据,然后通过应用程序完成。

我面临着同样的问题,苦苦挣扎了很长时间。