选择 打开 改范围 完整检索页

pgsql.cc 提供对 postgresql.org 官网内容的中文翻译,由 Pigsty 团队维护。

百科 / 错误代码 / Class 08 连接异常

08P01 protocol_violation

协议违规

ERROR 已实测 详解 实测通过

类别
Class 08 连接异常
严重等级
ERROR
条件名
protocol_violation
宏名称
ERRCODE_PROTOCOL_VIOLATION
启用版本
7.4
状态
活跃

版本覆盖

速览

SQLSTATE 08P01 是 Class 08 中的 protocol_violation08P01 表示前端/后端消息违反线路协议。选定原始 TCP 案例先完成启动并观察 ReadyForQuery(Z),再在合法帧中发送未知前端字节 Y,收到 C=08P01、S=FATAL、主报文 invalid frontend message type 89,并在客户端关闭 socket 前读到服务器 EOF。

含义

服务器协议解析器先接受启动交换,随后在派发 SQL 前拒绝未知的前端消息类型。选定路径为 FATAL invalid frontend message type 89,之后服务器发送 EOF;因此它是受影响 socket 的同步边界,不是 SQL 解析错误。

关键边界在于线路状态,而不是 SQL 文本。客户端可以已经到达 ReadyForQuery,却在下一条消息中发送错误类型,选定案例正是如此;启动帧损坏或代理改变帧边界也可能更早失败,并且可能没有可用会话。选定运行覆盖未知消息分派分支;下面的固定源码证据还覆盖不同的 Bind 和 message-buffer 解析分支,其他传输故障必须依据自身的 ErrorResponse 或日志判断。

08P01 并不意味着固定的严重级别或 socket 结果。在固定的 extended-query 路径中,Bind 消息的 parameter-format 数量或参数数量不匹配时报告 ERROR;顶层循环中止当前命令,等待协议规定的 Sync,然后才继续下一个 ReadyForQuery。固定的 message-buffer 读取器在缺少字节、字符串无效或报文尾部有数据时也使用 ERROR。这些可恢复的协议错误不同于未知消息类型:后者是 FATAL 边界,因为服务器不能再信任消息同步状态。

诊断

检查驱动或代理的协议版本、消息类型、帧长度、启动模式和连接所有权。选定证据中的 collector 是收集原始协议 ErrorResponse(C/S/M 及服务器 EOF)的对象,不是 csvlog/jsonlog。服务器关闭产生 FATAL 的 socket,案例不会复用它;独立的运行器连接能执行 SELECT 1 并保持 IDLE。这是线路协议边界,不是 SQL 语法,也不是客户端自行创建的 SQLSTATE。

按阶段解释恢复:

  • 启动完成前没有会话级事务,驱动可能只有连接异常;如果服务器发过响应,应保留原始线路记录。
  • 启动到达 Z 后,未知前端消息会在已建立后端中被拒绝,但选定分支是 FATAL,随后服务器关闭该 socket。即使客户端在协议失步前已经开始工作,也不能在这个 socket 上发送 ROLLBACK
  • 经过连接池或代理时,要比较所有者实际发送的字节与服务器期望的协议版本和帧格式。另一条连接上的 SELECT 1 只证明可达,不证明在途请求已经提交。

先根据主报文识别分支,再选择恢复动作。bind message has ... parameter formatsbind message supplies ... parameters 指向 extended-query 数量契约;no data left in messageinsufficient data left in messageinvalid string in messageinvalid message format 指向报文主体或边界损坏。这些源码定义的 ERROR 变体在驱动仍能保持帧边界时可能通过 Sync 恢复;带 FATALinvalid frontend message type ... 则表示选定 socket 已经失效。

处理

收到 FATAL 或服务器 EOF 时,关闭并丢弃受影响的 socket,修正协议或代理帧后重新连接。extended-query 的 ERROR 应让驱动发送协议有效的 Sync 并等待 ReadyForQuery,然后检查事务状态;Sync 不会回滚失败的显式事务,状态为 E 时仍须执行 ROLLBACK 或回到有意建立的保存点。若非幂等请求在途中,重放前先核对结果。独立探针只证明新连接可用。

将选定案例视为会话终止分支:读到服务器 EOF 后建立新连接,并且只重做已核对且具幂等性的操作。如果违规发生在会话建立前,应先修正启动或代理配置。只有客户端解析器异常或 socket 关闭而没有服务器 C 字段,不能把事件标成 08P01

不要自行拼接字节,也不要把事务当作已经提交。若驱动无法保持报文边界或不实现 Sync 契约,应丢弃连接并核对请求结果。这一源码流程不改变选定未知字节运行:该案例的 FATAL socket 必须丢弃。

可复现案例

在一次性实例上执行过的场景。其中 1 个附有可执行 SQL,正文相应小节里给出。

protocol_violation PG 10 / 18 有 SQL

前置条件

  • A runner-owned disposable target is provisioned.

触发

Complete a startup handshake, then send a correctly framed unknown frontend message type.

断言

  • The selected server diagnostic has the expected SQLSTATE
  • The selected recovery/probe assertions pass
  • Runner-owned resources are cleaned up

处置

Follow the case-specific repair statements and verify the resulting state.

清理

Drop the case schema with an owner connection.

报文

固定的协议解析路径以 FATAL 发出主报文 invalid frontend message type %d,其中字节数值是动态的。选定的 Y 字节记录为 89。SQLSTATE 的依据是原始 ErrorResponse,而不是客户端异常。

其他固定源码分支以 ERROR 发出以下主报文模板:

  • bind message has %d parameter formats but %d parameters
  • bind message supplies %d parameters, but prepared statement "%s" requires %d
  • no data left in message
  • insufficient data left in message
  • invalid string in message
  • invalid message format

这些 Bind 和 message-buffer 变体在本页中是源码证据,不是新增运行观察,也不会全部终止 socket。

选定的线路顺序是:启动交换 → Z ReadyForQuery → 合法帧中的类型字节 Y(十进制 89)→ ErrorResponse C=08P01S=FATALM=invalid frontend message type 89 → 服务器 EOF。collector 直接收集这些协议字段和 EOF,既不是 csvlog/jsonlog 记录,也不是后续独立探针。

报文模板

源码里的格式串,不是某一次运行的输出。%s 之类是占位符,实际报文会填入对象名与取值。适用范围一栏是核验时留下的原始英文记录,未经翻译。

主消息 invalid frontend message type %d

来源:src/backend/tcop/postgres.c @ REL_18_6 · src/backend/tcop/postgres.c @ REL_10_23

主消息 bind message has %d parameter formats but %d parameters

来源:src/backend/tcop/postgres.c @ REL_10_23

主消息 bind message supplies %d parameters, but prepared statement "%s" requires %d

来源:src/backend/tcop/postgres.c @ REL_10_23

主消息 no data left in message

来源:src/backend/libpq/pqformat.c @ REL_10_23

主消息 insufficient data left in message

来源:src/backend/libpq/pqformat.c @ REL_10_23

主消息 invalid string in message

来源:src/backend/libpq/pqformat.c @ REL_10_23

主消息 invalid message format

来源:src/backend/libpq/pqformat.c @ REL_10_23

代表案例

SQL 探针用于检查独立连接。真实触发是运行器拥有的 TCP 握手后发送未知前端消息字节,不能只用 SQL 表达。

SELECT 1;

18.6 服务器记录为 C=08P01、S=FATAL、主报文 invalid frontend message type 89;启动到达 Z,服务器 EOF 断言为 True,独立探针返回 1,状态 IDLE。因此没有复用触发错误的连接。

可下载的案例与证据投影分别是 08P01 案例 JSON作者证据。运行器清单为 verify/cases/08P01/cases.json;发布前会将页面 SQL 与共享注册表比对。

版本

上面的生成事实表记录锁定的目录快照和最早观察到的定义。本页自然运行范围是 PostgreSQL 18.6 与 10.21,不能据此推断所有中间版本的行为。

来源

证据

断言

每条断言都写明了是怎么核实的,以及它不覆盖什么。这一层是核验时留下的原始英文记录,照原样呈现,未经翻译。

  • 08P01 is the protocol_violation condition in Class 08.

    核实方式Read the fixed errcodes.txt definition and the locked catalogue metadata.

    不覆盖Directory identity does not identify every backend or client path.

    来源src/backend/utils/errcodes.txt

  • The fixed source paths associated with 08P01 report the condition in the mechanism selected for this page.

    核实方式Trace the resolved source call records at the fixed release commits and compare their dynamic message fields.

    不覆盖Other calls can retain the same SQLSTATE with different context or text.

    来源src/backend/tcop/postgres.c · src/backend/tcop/postgres.c

  • The fixed extended-query Bind path reports ERROR 08P01 for parameter-format cardinality mismatches or a parameter count that differs from the prepared statement. After an ERROR while processing an extended-query message, the top-level loop skips messages until a protocol-valid Sync and then resumes the normal ReadyForQuery flow; this ERROR path is distinct from the unknown frontend type FATAL branch.

    核实方式Read the complete REL_10_23 exec_bind_message branch and the surrounding top-level error-recovery and Sync handling in postgres.c.

    不覆盖This is a REL_10_23 source contract; no Bind or Sync runtime was selected in this batch, and a driver must send a valid Sync rather than arbitrary bytes.

    来源src/backend/tcop/postgres.c · src/backend/tcop/postgres.c

  • The fixed REL_10_23 pqformat readers report ERROR 08P01 for a depleted message, insufficient bytes, an invalid string, or trailing message data. These parser errors are source-only examples of protocol_violation and do not imply the unknown-message FATAL socket termination.

    核实方式Read pq_getmsgbyte, pq_getmsgbytes/pq_copymsgbytes, pq_getmsgstring/pq_getmsgrawstring, and pq_getmsgend in the fixed pqformat.c source.

    不覆盖The exact branch depends on the parser and message framing; this source scan does not select a natural runtime or generalize every malformed frame.

    来源src/backend/libpq/pqformat.c

  • The selected protocol_violation case passed with the expected structured diagnostics, recovery assertions, and cleanup on PostgreSQL 18.6 and 10.21.

    核实方式Run the shared registry case on isolated runner-owned latest and PG10 targets; inspect the final summaries and raw results.

    不覆盖This covers the selected case and versions only; it does not generalize to every driver, proxy, or intermediate release.

    来源verify/cases/08P01/snippets.json · verify/cases/08P01/cases.json

  • The selected unknown-message branch occurs after startup reaches ReadyForQuery, emits a FATAL ErrorResponse, and closes the affected socket; a pre-session protocol failure has no session transaction, and a client EOF without the server ErrorResponse is not sufficient to assign 08P01.

    核实方式Compare the fixed postgres.c dispatch path, the protocol error-field contract, and the selected raw collector sequence.

    不覆盖The selected runtime covers one unknown frontend byte and does not generalize to every framing, proxy, or startup failure.

    来源src/backend/tcop/postgres.c · doc/src/sgml/protocol.sgml

  • The locked catalogue records 08P01 in the listed snapshots; the runtime comparison here is limited to PostgreSQL 18.6 and 10.21.

    核实方式Read the generated facts block and locked manifest, then compare the selected target summaries.

    不覆盖Presence in a definition file is not an exact behavioral introduction; the two runtime targets do not prove all middle versions.

    来源src/backend/utils/errcodes.txt · raw/calls/REL_18_6.jsonl · raw/calls/REL_10_23.jsonl

运行记录

目标服务器版本结果覆盖案例
latest 18.6 (Homebrew) passed protocol_violation
pg10 10.21 (Debian 10.21-1.pgdg90+1) passed protocol_violation

同类错误代码

Class 08 连接异常 下的其他成员。