2025年9月25日: PostgreSQL 18 发布!
支持的版本: 当前 (18) / 17 / 16 / 15 / 14 / 13
开发版本: devel
不支持的版本: 12 / 11 / 10 / 9.6 / 9.5 / 9.4 / 9.3 / 9.2 / 9.1 / 9.0 / 8.4 / 8.3 / 8.2

54.1. 概述 #

协议有启动和正常运行两个独立阶段。在启动阶段,前端连接到服务器并进行身份验证,以使服务器满意。(这可能涉及单个消息,或根据所使用的身份验证方法而涉及多个消息。)如果一切顺利,服务器将发送状态信息给前端,最后进入正常运行。除了初始的启动请求消息外,协议的这部分由服务器驱动。

在正常运行期间,前端向后端发送查询和其他命令,后端则发送查询结果和其他响应。有几种情况(例如 NOTIFY),后端会发送未请求的消息,但绝大多数情况下,会话的这部分由前端请求驱动。

会话的终止通常由前端选择,但在某些情况下可能由后端强制执行。无论哪种情况,当后端关闭连接时,它将在退出前回滚任何已打开(未完成)的事务。

在正常运行中,可以通过以下两种子协议之一来执行 SQL 命令。在“简单查询”协议中,前端只需发送一个文本查询字符串,后端会立即对其进行解析和执行。在“扩展查询”协议中,查询的处理分为多个步骤:解析、参数值绑定和执行。这提供了灵活性和性能优势,但代价是增加了复杂性。

正常运行有其他子协议用于特殊操作,例如 COPY

54.1.1. 消息概述 #

所有通信都通过消息流进行。消息的第一个字节标识消息类型,接下来的四个字节指定其余消息的长度(此长度计数包括其本身,但不包括消息类型字节)。消息的其余内容取决于消息类型。出于历史原因,客户端发送的第一个消息(启动消息)没有初始的消息类型字节。

为了避免与消息流失去同步,服务器和客户端通常会在尝试处理其内容之前,将整个消息读取到缓冲区中(使用字节计数)。这使得在处理内容时检测到错误时易于恢复。在极端情况下(例如内存不足以缓冲消息),接收方可以使用字节计数来确定在恢复读取消息之前要跳过多少输入。

相反,服务器和客户端都必须小心,切勿发送不完整消息。这通常通过在开始发送之前将整个消息封存在缓冲区中来完成。如果在发送或接收消息的过程中发生通信故障,唯一明智的响应是放弃连接,因为几乎不可能恢复消息边界同步。

54.1.2. 扩展查询概述 #

在扩展查询协议中,SQL 命令的执行分为多个步骤。在步骤之间保留的状态由两种类型的对象表示:准备好的语句门户。准备好的语句表示对文本查询字符串进行解析和语义分析的结果。准备好的语句本身并不准备执行,因为它可能缺少参数的特定值。门户表示一个已准备好执行或已部分执行的语句,任何缺失的参数值都已填补。(对于 SELECT 语句,门户等同于一个打开的游标,但我们选择使用不同的术语,因为游标不处理非 SELECT 语句。)

整体执行周期包括一个解析步骤,该步骤从文本查询字符串创建准备好的语句;一个绑定步骤,该步骤根据准备好的语句和任何所需参数的值创建门户;以及一个执行步骤,该步骤运行门户的查询。对于返回行的查询(SELECTSHOW 等),可以指示执行步骤仅获取有限数量的行,因此可能需要多个执行步骤来完成操作。

后端可以跟踪多个准备好的语句和门户(但请注意,这些仅存在于会话中,并且从不跨会话共享)。现有的准备好的语句和门户通过创建时分配的名称来引用。此外,还存在一个“未命名”的准备好的语句和门户。尽管它们在很大程度上与命名对象行为相同,但对它们的と操作针对的是仅执行一次然后丢弃查询的情况进行了优化,而对命名对象的操作则针对的是期望多次使用的情况进行了优化。

54.1.3. 格式和格式代码 #

特定数据类型的数据可能以几种不同的格式传输。截至 PostgreSQL 7.4,唯一支持的格式是“文本”和“二进制”,但协议为将来的扩展提供了规定。任何值的所需格式由格式代码指定。客户端可以为每个传输的参数值和每个查询结果列指定一个格式代码。文本的格式代码为零,二进制的格式代码为一,所有其他格式代码均保留供将来定义。

值的文本表示就是特定数据类型的输入/输出转换函数生成的字符串。在传输的表示中,没有尾随的 null 字符;如果前端想将接收到的值作为 C 字符串处理,它必须为其添加一个。(顺便说一句,文本格式不允许嵌入 null。)

整数的二进制表示使用网络字节序(最高有效字节在前)。对于其他数据类型,请查阅文档或源代码以了解二进制表示。请记住,复杂数据类型的二进制表示可能会在服务器版本之间发生变化;文本格式通常是更具可移植性的选择。

54.1.4. 协议版本 #

当前最新的协议版本是 3.2。但是,为了向后兼容不支持版本协商的旧服务器版本和中间件,libpq 默认仍使用协议版本 3.0。

单个服务器可以支持多个协议版本。初始的启动请求消息告知服务器客户端尝试使用的协议版本。如果客户端请求的主版本不受服务器支持,连接将被拒绝(例如,如果客户端请求协议版本 4.0,而此版本在撰写本文时不存在,则会发生这种情况)。如果客户端请求的次版本不受服务器支持(例如,客户端请求版本 3.2,但服务器仅支持 3.0),服务器可以拒绝连接,或者以 NegotiateProtocolVersion 消息响应,其中包含其支持的最高次协议版本。然后,客户端可以选择继续使用指定的协议版本进行连接,或中止连接。

协议协商已在 PostgreSQL 版本 9.3.21 中引入。早期版本如果客户端请求的次版本不受服务器支持,则会拒绝连接。

表 54.1 显示了当前支持的协议版本。

表 54.1. 协议版本

版本 由...支持 描述
3.2 PostgreSQL 18 及更高版本 当前最新版本。用于查询取消的密钥长度从 4 字节增加到可变长度字段。BackendKeyData 消息已更改以适应这一点,CancelRequest 消息已重新定义为具有可变长度的负载。
3.1 - 保留。版本 3.1 未被任何 PostgreSQL 版本使用,但它被跳过了,因为流行的 pgbouncer 应用程序的旧版本在协议协商中存在一个错误,导致它错误地声称支持版本 3.1。
3.0 PostgreSQL 7.4 及更高版本  
2.0 最高达 PostgreSQL 13 有关详细信息,请参阅 PostgreSQL 文档的先前版本。

提交更正

如果您在文档中看到任何不正确、与您对特定功能的体验不符或需要进一步澄清的内容,请使用 此表单 报告文档问题。