最近我的 PostgreSQL 8.2.4 记录了这样的错误:
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 时,问题就开始了。查询产生 0 行,但是当我仅通过 relname/tgname 查询表时,我得到不同的 OID,就像触发器在不同的表上一样。我做了一个快速测试,结果显示创建一个带有触发器的简单表会产生相同的结果。
所以我的问题是:
当我可以在 pg_class 中找到表时,如何导航 pg_trigger(以及其他 pg 表,如 pg_attribute、pg_shdepend)表?
如果我以某种方式设法找到对有问题的 OID 的引用,我是否可以安全地通过对 pg_class 表进行直接更新/删除来简单地删除该引用?
最佳答案
请注意,'reltype' 是表行类型的 OID - 表本身的 OID 是 pg_class.oid
(这是一个系统列,因此不会出现在 中\d
或 select *
输出,需要明确选择)。
希望这将解决目录表如何相互关联的一些谜团!对于使用 oid 作为主键的许多其他表重复相同的模式。
这看起来是一个相当严重的问题,可能表示某种目录损坏?您可以直接修改 pg_class
等,但显然这样做存在一些风险。我想不出有多少通用的建议可以在这里给出 - 根据您的发现,做什么会有很大的不同。
关于postgresql - 追踪 "could not open relation with OID"错误的原因,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5030720/