PostgreSQL 使用基于消息的协议在前端和后端(客户端和服务器)之间进行通信。 T 端口号 5432 已在 IANA 注册为支持此协议的服务器的惯用 TCP 端口号,但实际上可以使用任何非特权端口号。
什么是 PostgreSQL?
PostgreSQL,也称为 Postgres,是一种开源关系数据库,因其可靠性、灵活性和对开放技术标准的支持而享有盛誉。 PostgreSQL 支持非关系和关系数据类型。 它被称为当今可用的最兼容、最稳定和最成熟的关系数据库之一,并且可以轻松处理复杂的查询。
PostgreSQL通信流程
PostgreSQL在TCP三次握手后进行通信流程。PostgreSQL协议具有用于启动和查询操作的单独阶段。
客户端发起的通信的设备向服务器发送一个TCP数据包。这个初始数据包除了底层协议头之外不包含任何数据。这个数据包的TCP头设置了SYN标识,并包含了在通信过程中会用到的初始序列号和最大分段大小。服务器对于这个数据包回复了一个类似的设置SYN和ACK标志以及包含了它初始序列号的数据包。
最后,客户端向服务器发送最后一个仅设置了ACK标志的数据包。在这个过程完成了之后,双方设置应该已经具有了开始正常通信所需的信息。
启动第一阶段
在启动阶段,前端打开与服务器的连接并验证自己以使服务器满意。 如果一切顺利,服务器将状态信息发送到前端,最后进入正常操作。除了初始启动请求消息外,这部分协议由服务器驱动。
- Start-up Message
要开始会话,PostgreSQL的启动包由客户端发出。客户端会打开与服务器的连接并发送启动消息。该消息包括用户名和用户想要连接的数据库的名称,它还标识要使用的特定协议版本。
Type:消息类型
Length:长度
Protocol major version:标识使用的特定版本
Protocol minor version:标识使用的特定版本
Parameter name :数据库登陆用户名
Parameter value:连接的数据库的名称
启动阶段,客户端向服务端发送了一条StartupMessage
Authentication request
服务器收到后,会进行判断,该用户是否需要密码认证,如果需要则会发送一个Authentication request来请求密码认证信息。
Type:Authentication request(R)
Length:长度
Authentication type:5(MD5 password)
- Password message
Type:Password message§
Length:长度
Password:password值
- Parameter Status
前端此时发送密码认证成功后,后端会开始发送各种Parameter Status,也就是一系列后端参数,比如数。
ParameterStatus 这个报文告诉前端当前配置参数,例如 client_encoding 或者 DataStyle 。前端可以忽略此报文,或者记录下来供以后使用。前端无需响应此报文,但是应该继续等ReadyForQuery报文。
查询第二阶段
正常运行时,前端向后端发送查询等命令,后端发回查询结果等响应。
- Simple Query
一个简单的查询周期是由前端向后端发送一条查询消息来启动的。 该消息包括一个以文本字符串表示的 SQL 命令(或多个命令)。 然后后端根据查询命令字符串的内容发送一条或多条响应消息,最后发送一条 ReadyForQuery 响应消息。
Parse : ‘P’ 预处理语句,报文中包含报文长度,命令类型和具体命令的语句等等。在PostgreSQL中叫扩展查询,预处理查询会在查询时候先输入语句进行预处理,语句内部含有一些标识符,代表参数,后面执行的时候再将参数进行填充执行。
对 SELECT 查询的响应通常包括 RowDescription、零个或多个 DataRow 消息,然后是 CommandComplete。复制到或从前端调用特殊协议,所有其他查询类型通常只产生一个 CommandComplete 消息。
CommandComplete :一个SQL命令正常结束。
由于一个查询字符串可能包含多个查询(以分号分隔),因此在后端完成对查询字符串的处理之前可能会有多个这样的响应序列。当整个字符串被处理并且后端准备好接受一个新的查询字符串时,ReadyForQuery 被发出。
如果接收到一个完全空的(除空白之外没有其他内容)查询字符串,则响应为 EmptyQueryResponse,后跟 ReadyForQuery。
如果发生错误,将发出 ErrorResponse,然后是 ReadyForQuery。查询字符串的所有进一步处理都被 ErrorResponse 中止(即使其中还有更多查询)。请注意,这可能发生在单个查询生成的消息序列的中途。
在简单查询模式下,检索值的格式始终为文本,除非给定命令是来自使用 BINARY 选项声明的游标的 FETCH。在这种情况下,检索到的值是二进制格式。 RowDescription 消息中给出的格式代码说明正在使用哪种格式。
PostgreSQL的客户端命令类型
主要包含以下信息:
{ 'p', "Authentication message" },
{ 'Q', "Simple query" },
{ 'P', "Parse" },
{ 'B', "Bind" },
{ 'E', "Execute" },
{ 'D', "Describe" },
{ 'C', "Close" },
{ 'H', "Flush" },
{ 'S', "Sync" },
{ 'F', "Function call" },
{ 'd', "Copy data" },
{ 'c', "Copy completion" },
{ 'f', "Copy failure" },
{ 'X', "Termination" },
PostgreSQL的服务器命令类型
主要包含以下信息:
{ 'R', "Authentication request" },
{ 'K', "Backend key data" },
{ 'S', "Parameter status" },
{ '1', "Parse completion" },
{ '2', "Bind completion" },
{ '3', "Close completion" },
{ 'C', "Command completion" },
{ 't', "Parameter description" },
{ 'T', "Row description" },
{ 'D', "Data row" },
{ 'I', "Empty query" },
{ 'n', "No data" },
{ 'E', "Error" },
{ 'N', "Notice" },
{ 's', "Portal suspended" },
{ 'Z', "Ready for query" },
{ 'A', "Notification" },
{ 'V', "Function call response" },
{ 'G', "CopyIn response" },
{ 'H', "CopyOut response" },
{ 'd', "Copy data" },
{ 'c', "Copy completion" },
{ 'v', "Negotiate protocol version" },
PGSQL协议解析及C/C++代码实现
void dissect_pgsql_msg(u_char *pgsql_data,int offset,struct tcphdr *pTcpHdr,int payload_len)
{
conn_data = (pgsql_conn_data_t *)malloc(sizeof(pgsql_conn_data_t));
if ( conn_data == NULL)
{
printf("conn_data fail!!!\n");
return ;
}
conn_data->ssl_requested = false;
conn_data->auth_state = PGSQL_AUTH_STATE_NONE;
type = pgsql_data[n + 0];
if (type != '\0')
n += 1;
length = ntohl(pgsql_data + n);
if (fe)
{
if (type == '\0')
{
unsigned int tag = ntohl(pgsql_data + n + 4);
if (length == 16 && tag == 80877102)
typestr = "Cancel request";
else if (length == 8 && tag == 80877103)
typestr = "SSL request";
else if (length == 8 && tag == 80877104)
typestr = "GSS encrypt request";
else if (tag == 196608)
typestr = "Startup message";
else
typestr = "Unknown";
}
else if (type == 'p')
{
switch (conn_data->auth_state)
{
case PGSQL_AUTH_SASL_REQUESTED:
typestr = "SASLInitialResponse message";
break;
case PGSQL_AUTH_SASL_CONTINUE:
typestr = "SASLResponse message";
break;
case PGSQL_AUTH_GSSAPI_SSPI_DATA:
typestr = "GSSResponse message";
break;
default:
typestr = "Password message";
break;
}
}
else
typestr = val_to_str_const(type, fe_messages, "Unknown");
}
else
{
typestr = val_to_str_const(type, be_messages, "Unknown");
}
...
}
解析结果:
PostgreSQL 的好处?
PostgreSQL 的一些主要优点:
1、性能和可扩展性——包括地理空间支持和无限制的并发性——以及跨多种数据类型的深入、广泛的数据分析。
2、通过使用多版本并发控制 (MVCC) 支持并发,这使得写操作和读操作同时发生。
3、由于其兼容性和对多种编程语言的支持,包括 Python、Java、JavaScript、C/C++ 和 Ruby,因此具有深度语言支持。
4、业务连续性,通过跨服务器的异步或同步复制方法提供高可用性服务。
5、通过开源数据库管理技术实现更大的灵活性和成本效益的创新。
欢迎关注微信公众号【程序猿编码】,需要PGSQL完整源码和报文请添加本人微信号(c17865354792)
参考:https://www.postgresql.org/