跳转到主要内容

XX000 — internal_error(内部错误)

PostgreSQL 使用 SQLSTATE XX000 表示内部错误路径,也把没有显式代码的 ERROR 默认映射到这里。应保留完整诊断并调查具体子系统;XX000 本身不能证明数据损坏。

速览

XX000 是类别 XX Internal Error 中的 internal_error 条件。PostgreSQL 源码目录把这个类别描述为“本不应发生”的条件和软件缺陷。它是通用的诊断边界,不能据此断言数据库已经损坏。

这个代码也有机械的默认来源。在错误栈初始化时,没有后续显式代码的 ERROR 或更高级别会先使用 ERRCODE_INTERNAL_ERRORWARNING 级别从 ERRCODE_WARNING01000)开始;低于 WARNING 的级别若没有自己的代码则从 00000 开始。显式 errcode() 可以选择其他 SQLSTATE。因此,XX000 可能来自没有显式 SQLSTATE 的默认 elog(ERROR, ...) 路径,也可能来自主动报告内部错误的路径。

严重级别和连接后果取决于具体路径。ERRORFATALPANIC 是不同的协议严重级别;扩展测试代码甚至可以在 NOTICE 中显式携带 XX000。应把严重级别、事务状态、连接状态、源码位置和完整诊断放在一起读取。

代表性案例 internal_error_safety_boundary 只做源码核验,未实测自然触发路径。由于强行制造内部损坏或故障会越过安全的临时数据库边界,PostgreSQL 18.6 和 10.21 上均记录为 not_applicable,也没有用手写 RAISE 冒充服务器内部失败。

字段
SQLSTATE XX000
条件名 internal_error
状态 有效
已知存在于 7.4
锁定快照 9.0.23, 9.1.24, 9.2.24, 9.3.25, 9.4.26, 9.5.25, 9.6.24, 10.23, 11.22, 12.22, 13.23, 14.24, 15.19, 16.15, 17.11, 18.6, 19beta3
ERRCODE_INTERNAL_ERROR
别名

含义与触发路径

18.6 的定义是在类别 XX 下的 XX000 E ERRCODE_INTERNAL_ERROR internal_error。这个类别注释有意保持宽泛。对于数据损坏(XX001)和索引损坏(XX002)还有更具体的代码;选用 XX000 不会自动把通用内部报文升级成这两种诊断。

需要区分两种源码模式:

  1. 默认内部代码。 后端路径调用没有显式 SQLSTATE 的 elog(ERROR, ...),或以同样方式到达 ereport(ERROR, ...)elog.c 会把这个错误初始化为 XX000,但报文和源码函数仍能指出所属子系统。
  2. 显式内部代码。 某条路径调用 errcode(ERRCODE_INTERNAL_ERROR),因为某个不变量或操作系统/服务结果被视为不可能或不可用。18.6 中的例子包括 B-tree 重检时无法重新找到索引元组、动态共享内存控制段无效、尝试重新定义非占位配置参数,以及 UUID 生成无法取得强随机字节。

显式代码不会强制唯一的严重级别。共享内存路径报告 FATAL,而 B-tree、GUC 和 UUID 例子报告 ERROR。一个访问控制测试钩子还会在 NOTICE 中显式报告 ERRCODE_INTERNAL_ERROR,说明 SQLSTATE 与严重级别是分开的字段。这个钩子只是源码例子,不是普通生产提示表示内部故障的证据。

报文与诊断

XX000 没有统一的主报文。源码中可见的代表性模板包括:

  • failed to re-find tuple within index "%s",并提示索引表达式可能不是不可变的(nbtinsert.c)。
  • dynamic shared memory control segment is not valid,出现在 FATAL 初始化路径(dsm.c)。
  • attempt to redefine parameter "%s"guc.c)和 could not generate random valuesuuid.c)。
  • 默认 elog(ERROR, ...) 路径中的 invalid page pd_lower %u pd_upper %u pd_special %ubufmask.c);没有其他显式代码替换时,默认映射会提供 XX000

这些都是具体路径的诊断模板。应记录 SQLSTATE、两种严重级别字段、主报文、详细信息、提示、上下文、源码文件、函数、行号、后端 PID、数据库和服务器版本。本地化文本和模板措辞可能变化;源码路径和结构化字段比报文子串更稳定。

诊断

在重试或重启前保留完整的客户端错误和对应服务器日志。先按协议严重级别分类:

  • ERROR 通常会中止当前显式事务,但回滚后后端连接仍可使用。
  • FATAL 会结束后端会话,客户端需要建立新连接才能继续。
  • PANIC 是影响服务器的紧急路径,进程和连接后果必须根据服务器日志和进程监管状态确认。
  • 显式携带 XX000WARNINGNOTICE 具有不同控制流,单凭它既不能证明内部故障,也不能断言事务中止。

随后按源码函数和子系统归类。检查是否有先发生的 I/O、内存、扩展、索引、配置或并发故障;比对确切服务器构建和固定源码版本;寻找是否重复出现。只有当诊断指向相关对象时,才使用只读的目录、索引或页面检查。不能仅凭类别名推断损坏,也不要用手写 RAISE EXCEPTION 来制造复现:那默认测试的是 P0001,不是服务器内部路径。

处理

按照严重级别和子系统处理。ERROR 要先回滚事务再发无关命令;FATAL 后重新建立连接;PANIC 后遵循服务器重启和事故流程。内部错误若源码指向不变量、存储、索引或共享内存边界,不应盲目重试。

收集服务器版本、确切 SQL、后端和服务器日志、源码位置、关系对象或其他对象身份,以及近期配置和扩展变化。如果证据指向损坏,应根据事故流程在适当时停止写入,保留副本或快照,并使用 PostgreSQL 文档化的恢复与支持流程。如果证据指向没有损坏迹象的软件或扩展缺陷,则隔离可复现条件并比较受支持的版本。正确处理取决于这些证据,而不是 XX000 本身。

版本

目录记录 XX000 存在于锁定的 7.4–8.4.22 pre-9.0 正式源码、9.0.23 至 18.6 的全部正式快照及 19 Beta 3 预览快照。同 tag 的 REL8_1_4 errcodes.sgml 表已经列出 XX000 和条件名 internal_error,因此至少可以确认 8.1.4 已有该条件名。9.0 头文件视图中的类标题为 Internal Error (PostgreSQL-specific error class),到 9.1 的文本定义变为 Internal Error。7.0–7.3 仍有候选源码缺口;这些是目录观察边界,不是确切实现引入日期的断言。

18.6 固定源码 commit 为 724edf9bde9d356724ad384a2e196edc3c9f80f7。默认严重级别到代码的映射以及上面的源码路径均有 18.6 证据。代表性运行案例没有接受确定且安全的 SQL 触发方式,因此两个目标的运行时状态均保持 not_applicable

XX001data_corruptedXX002index_corrupted 是更具体的损坏条件。P0001raise_exception 是没有代码的 PL/pgSQL RAISE EXCEPTION 的通常默认值。57P01admin_shutdown 是不同类别的服务器连接事件。25P02in_failed_sql_transaction 是前一个错误导致的后续事务状态,不是 XX000 的同义词。

来源

结构化证据记录在公开证据 JSON中。源码记录固定到 PostgreSQL commit 724edf9bde9d356724ad384a2e196edc3c9f80f7;运行时记录保留精确的源码边界案例 ID 和两个目标摘要。

  • src.errcodes.18.6errcodes.txt
  • src.elog.18.6elog.c
  • src.nbtinsert.18.6src.dsm.18.6src.guc.18.6src.uuid.18.6src.bufmask.18.6 — 源码确认的内部路径
  • src.oat-hooks.18.6 — 在 NOTICE 中显式提供内部代码
  • doc.protocol.18Error and Notice Message Fields