2011-02-17 13 views
4

就在最近我的PostgreSQL 8.2.4日志这种错误的原因:跟踪“可以与OID不开关系”错误

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

错误总是引起同样的情形:更新表A的原因触发器触发,它将数据插入表B,触发另一个触发器(在许多其他事物中)在表C上选择。然后,表C上的选择将作为上述问题的CONTEXT报告。导致错误消息出现的查询序列每天都会执行,并且每天都会报告缺少相同的OID。

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

所以我的问题是:

  1. 如何浏览pg_trigger(和其他PG表像pg_attribute里,pg_shdepend)表时,我可以在pg_class里找到表?

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

+1

版本8.2.4已经很老了,已经过时了,你(此时)16个补丁后面:8.2.20是最新的。这是4年没有任何维护... Digg到所有的发布说明,看看这个问题是否已经修复。 – 2011-02-17 15:17:48

回答

4

注意“reltype”是表的的rowtype-表本身的OID的OID被pg_class.oid(这是一个系统列,因此不\dselect *输出显示出来,你需要明确选择它)。

希望这将解决目录表如何相互关联的一些奥秘!使用oid作为主键的相当多的表格重复了相同的模式。

看起来相当严重的问题,可能表明某种目录损坏?你可以直接修改pg_class等,但显然这样做有一定的风险。我想不出多少通用的建议给予这里 - 做什么将取决于你发现的差异很大。

+2

这正是我所需要的。毕竟这个问题变得琐碎。其中一个功能取决于前一段时间被删除和重新创建的表。不知何故,该功能正在使用已删除的表的OID。只需重新创建函数和触发器(使其获得当前的OID)即可解决问题。 – 2011-02-18 16:09:33

0

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