【问题标题】:tracing the cause of "could not open relation with OID" error追查“could not open relationship with OID”错误原因
【发布时间】:2019-12-18 18:11:03
【问题描述】:

最近我的 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,就像触发器在不同的表上一样。我做了一个快速测试,似乎创建一个带有触发器的简单表会产生相同的结果。

所以我的问题是:

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

  2. 如果我设法找到了对有问题的 OID 的引用,我是否可以安全地通过对 pg_class 表进行直接更新/删除来简单地删除该引用?

【问题讨论】:

  • 版本 8.2.4 非常旧且过时,您(此时)落后了 16 轮补丁:8.2.20 是最新的。那是 4 年没有任何维护...深入研究所有发行说明,看看这个问题是否已得到修复。

标签: postgresql


【解决方案1】:

请注意,'reltype' 是表的行类型的 OID - 表本身的 OID 是 pg_class.oid(这是一个系统列,因此不会出现在 \dselect * 输出中,您需要明确选择它)。

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

这看起来是一个相当严重的问题,可能表明某种目录损坏?您可以直接修改pg_class 等,但显然这样做存在一些风险。我想不出太多通用的建议可以在这里给出——根据你的发现,做什么会有很大的不同。

【讨论】:

  • 这正是我所需要的。毕竟问题变得很琐碎。其中一项功能取决于前一段时间被删除和重新创建的表。不知何故,该函数正在使用已删除的表的 OID。只需重新创建函数和触发器(使它们获取当前 OID)即可解决问题。
【解决方案2】:

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

【讨论】:

    【解决方案3】:

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

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

    我也面临同样的问题,并且挣扎了很长时间。

    【讨论】:

      猜你喜欢
      • 2017-07-11
      • 2020-01-10
      • 2014-08-17
      • 2022-12-02
      • 2016-04-24
      • 2015-10-20
      • 1970-01-01
      • 1970-01-01
      • 2022-06-21
      相关资源
      最近更新 更多