0 开场白
时过两年多疫情依然肆虐,一波接一波,又逢晴空万里的清明假期, 一瓶沙洲优黄下肚,决定要写点东西。
结合自己近期工作内容,本文将详细介绍PG常用协议并举例如何用Go语言实现链接查询等,由于水平有限,不到之处就当酒后胡言,轻喷... >_<
1 PG前后端协议
本文基于3.0版本协议,主要以图示方式更为形象的描述其中比较重要的链接、查询等协议,详尽的文字说明可参考官方文档《Chapter 53. Frontend/Backend Protocol》或中文文档《第 53 章 前端/后端协议》。
1.1 整体流程视图
总体流程
协议大致可以分为 startup、normal两个阶段,startup阶段即建立链接阶段,包含ssl、认证、链接参数等;normal阶段即为发起SQL查询等的阶段。
1.2 Startup阶段
startup阶段流程
(1)一般客户端在建立链接时会先询问服务端是否开启SSL加密,若开启则服务器回复'S',客户端则进行SSL握手等,若不开启则回复'N'。
(2)客户端向服务器发送 StartupMessage 启动包,服务端判断是否需要认证,若需要则发送AuthenticationRequest信息,若不需要认证或已认证则可发送AuthenticationOk,认证失败响应ErrorResponse。
PG支持多种方式认证如:AuthenticationKerberosV5、AuthenticationCleartextPassword、AuthenticationMD5Password等,后面示例将采用常见的AuthenticationMD5Password方式进行演示。
(3)认证通过后服务端一般会发送三条消息:ParameterStatus如版本号、编码格式等;BackendKeyData包括当前链接进程id、取消链接的密钥;ReadForQuery 客户端收到这条消息后表示启动成功,前端现在可以发出命令到服务端。
(4)消息报文格式
启动消息报文格式
如上图,启动报文格式一般包含消息长度4个字节(包含自身)、协议类型编号4个字节、参数键值对等。
1.3 normal阶段
此部分主要讲解两种查询协议Simple Query、 Extended Query,其他协议先不做讲解,感兴趣可查阅文档学习。
此两种协议消息报文格式一般为:
Query消息协议报文
1.3.1 Simple Query 协议
Simple Query流程
如上图:
(1)客户端向服务端发起Query请求;
(2)服务端收到后立即处理,并将结果分三种类型消息返回:
RowDescription:表字段信息描述,包括字段名、字段类型等信息;
DataRow:数据信息,每条信息仅包含一行数据,如查询数据有10条,则会发送10条DataRow类型消息;
CommandComplete:表示本次查询完成,并返回处理了多少条数据,如select到10条数据,消息体为 SELECT 10;
(3)服务端向客户端发送ReadyForQuery,表示可以接收下一条命令;该消息类型中包含三种消息类型标识:
'I':表示操作不在事物内;
'T':表示操作处在事物中;
'E':在失败的事物中;
(4)消息报文示例
Simple Query消息报文
1.3.2 Extended Query 协议
相比于Simple Query,使用 Extended Query 时,发送请求的过程被分为若干步骤,准备步骤的结果可以被多次复用以提高效率;另外,还可以获得额外的特性, 比如可以把数据值作为独立的参数提供而不是必须把它们直接插入一个查询字符串。通常包括 Parse、Describe、Bind 和 Execute等。
因排版问题,无法一次性发布长文,详见知乎版本: