技术贴 | 深度解析 PostgreSQL Protocol v3.0(三)— 流复制(下)
文摘
科技
2024-08-06 18:20
上海
“PostgreSQL Protocol
v3.0 深度解析系列博客,主要围绕 PostgreSQL
Protocol 3.0 版本具体实现和大家做分享,相关的代码解读基于 PostgreSQL 代码仓库的 REL_14_STABLE 分支。在上篇博客中,我们重点介绍了流复制概念、复制命令及逻辑流复制协议,本期将重点介绍扩展查询及消息格式、流复制交互流程。
1. Query(F:'Q'),Query 消息格式如下:
2. CopyInResponse(B:'G'),CopyInResponse 消息格式如下:
将消息标识为 Start Copy In 响应。客户端现在必须发送复制数据。如果客户端不准备这样做,需要发送 CopyFail 消息。0:表示整个 COPY 格式是文本格式(行用换行符分隔,列用分隔符分隔,等等)。1:表示整个 COPY 格式是二进制的,类似于 DataRow 格式。用于每列的格式代码。每个值必须为 0(文本)或 1(二进制)。如果整个 COPY 格式是文本格式,则所有值必须为 0。3. CopyOutResponse(B:'H'),CopyOutResponse 消息格式如下:
将消息标识为 Start Copy Out 响应,后跟复制数据。0:表示整个 COPY 格式是文本格式(行用换行符分隔,列用分隔符分隔,等等)。1:表示整个 COPY 格式是二进制的,类似于 DataRow 格式。用于每列的格式代码。每个值必须为 0(文本)或 1(二进制)。如果整个 COPY 格式是文本格式,则所有值必须为 0。4. CopyBothResponse(B:'W'),CopyBothResponse 消息格式如下:
将消息标识为 Start Copy Both 响应。此消息仅用于流式复制。0:表示整个 COPY 格式是文本格式(行用换行符分隔,列用分隔符分隔,等等)。1:表示整个 COPY 格式是二进制的,类似于 DataRow 格式。用于每列的格式代码。每个值必须为 0(文本)或 1(二进制)。如果整个 COPY 格式是文本格式,则所有值必须为 0。5. CopyData(F&B:'d'),CopyData 消息格式如下:构成 COPY 数据流的一部分数据。从服务端发送的消息总是对应于单个数据行,但客户端发送的消息可能会任意划分数据流。6. CopyDone(F&B:'c'),CopyDone 消息格式如下:消息内容的字节长度,包括自身 4 个字节。值总是为 4。7. CopyFail(F:'f'),CopyFail 消息格式如下:8. RowDescription(B:'T'),RowDescription 消息格式如下:如果字段可以被标识为特定表的列,则值为该表的对象 ID;否则为 0。如果该字段可以标识为特定表的列,则值为该列的属性编号;否则为 0。数据类型大小(可以参考 pg_type.typlen)。需要注意的是,负值表示可变宽度类型。类型修饰符(可以参考 pg_attribute.atttypmod)。修饰符的含义是特定于数据类型的。字段的格式代码。目前,只能是 0(文本)或 1(二进制)。在从 Describe 语句请求返回的 RowDescription 中,格式代码还未知,并且始终为零。蓝色背景的部分,是每个列的详细描述。浅灰色背景的部分是可选的,格式是蓝色部分的重复。9. DataRow(B:'D'),DataRow 消息格式如下:列值的长度,以字节为单位(此计数不包括长度字段自身的 4 个字节)。该字段值可以为零。作为一种特殊情况,-1 表示列值为 NULL。在列值为 NULL 的情况下,后面没有值字节的字段。列的值,格式由关联的格式代码指示。n 是上述字段的长度值。蓝色背景的部分,是每个列值的字节长度和列值,是可选的。浅灰色背景的部分是可选的,格式是蓝色部分的重复。10. CommandComplete(B:'C'),CommandComplete 消息格式如下:命令标记。这通常是一个单词,用于标识完成了哪个 SQL 命令。- 对于 INSERT 命令,标记是 INSERT oid rows,其中 rows 是插入的行数。如果 rows 为 1 并且目标表具有 oid,则 oid 表示插入行的对象 ID。但 OIDs 系统列不再受支持;因此 oid 总是 0。
- 对于 DELETE 命令,标记为 DELETE rows,其中 rows 是删除的行数。
- 对于 UPDATE 命令,标记是 UPDATE rows,其中 rows 是更新的行数。
- 对于 SELECT 或 CREATE TABLE AS 命令,标记是 SELECT rows,其中 rows 是检索的行数。
- 对于 MOVE 命令,标记为 MOVE rows,其中 rows 是游标位置已更改的行数。
- 对于 FETCH 命令,标记是 FETCH rows,其中 rows 是从游标检索的行数。
- 对于 COPY 命令,标记是 COPY rows,其中 rows 是复制的行数。(注意:行计数仅出现在 PostgreSQL 8.2 及更高版本中。)
11. Flush(F:'H'),Flush 消息格式如下:消息内容的字节长度,包括自身 4 个字节。始终为 4。12. Sync(F:'S'),Sync 消息格式如下:消息内容的字节长度,包括自身 4 个字节。值始终为 4。13. ErrorResponse(B:'E'),ErrorResponse 消息格式如下:消息体由一个或多个标识字段组成,后跟一个 '\0' 字节作为终止符。字段可以按任何顺序出现。对于每个字段,都有以下内容:- String 字段值。蓝色背景的部分,是消息体的一个字段类型及其值以及结束符 '\0'。一个 ErrorResponse 消息至少包含一个消息体,浅灰色背景的部分是可选的,格式是蓝色部分的重复。消息体的最后,有一个 '\0' 作为消息的结束。
14. ReadyForQuery(B:'Z'),ReadyForQuery 消息格式如下:将消息标识为服务器端准备好接收客户端的查询请求类型。每当服务器为新的查询周期做好准备时,就会发送 ReadyForQuery。消息内容的字节长度,包括自身 4 个字节。值总是 5。○ Byte1 当前服务器端事务状态指示器。可能的值为:'I':处于空闲状态(不在事务块中); 'T':在事务块中; 'E':在失败的事务块中(查询将被拒绝,直到事务块结束)。15. ParameterStatus(B:'S'),ParameterStatus 消息格式如下:16. NoticeResponse(B:'N'),NoticeResponse 与 ErrorResponse 消息格式以及消息体的内容完全一致。消息格式如下:消息体由一个或多个标识字段组成,后跟一个'\0'字节作为终止符。字段可以按任何顺序出现。对于每个字段,都有以下内容:- String,字段值。蓝色背景的部分,是消息体的一个字段类型及其值以及结束符'\0'。一个 NoticeResponse 消息至少包含一个消息体,浅灰色背景的部分是可选的,格式是蓝色部分的重复。消息体的最后,有一个'\0'作为消息的结束。
流复制交互流程,主要包括 COPY-IN、COPY-OUT 和 COPY-BOTH 三种模式,COPY-BOTH 模式又分为物理复制模式和逻辑复制模式。下面将对集中模式的交互流程分别进行介绍。1. 客户端发起包含 COPY FROM STDIN 的 Query 查询消息。2. 服务器端接收到 COPY FROM STDIN 查询消息,将连接切换到 COPY-IN 模式。切换模式成功后,向客户端发送 CopyInResponse 消息。3. 客户端向服务器端发送数据消息 CopyData,可能为一个或多个,数据发送完成之后,发送 CopyDone 消息。4. 服务器端接收到 CopyDone 消息,结束 COPY-IN 模式,恢复到 COPY-IN 模式之前的 SQL 命令处理流程。然后向客户端发送 CommandComplete 消息和 ReadyForQuery 消息。1. 客户端发起包含 COPY TO STDOUT 的 Query 查询消息。2. 服务器端接收到 COPY TO STDOUT 查询消息,将连接切换到 COPY-OUT 模式。切换模式成功后,向客户端发送 CopyOutResponse 消息。3. 紧接着,服务器端向客户端发送数据消息 CopyData,可能为一个或多个,数据发送完成之后,发送 CopyDone 消息。4. 服务器端发送 CopyDone 消息后,结束 COPY-OUT 模式,恢复到 COPY-OUT 模式之前的 SQL 命令处理流程。然后向客户端发送 CommandComplete 消息和 ReadyForQuery 消息。COPY-BOTH 模式主要包括物理复制模式、逻辑复制模式和 BASE_BACKUP 模式,三种模式在交互流程上略有不同。下面分别对物理复制模式、逻辑复制模式和 BASE_BACKUP 模式的交互流程进行详细介绍。1. 客户端发起连接,向服务器端发送 StartupMessage 消息,包含参数 replication,值设置为 true,或 on,或 yes,或 1。2. 服务器端接收到连接启动消息和 replication 参数,进入物理复制 WAL 发送者模式。3. 可选,客户端发送包含 IDENTIFY_SYSTEM 查询字符串的 Query 消息。服务器端返回 DataRow 消息和 CommandComplete 消息。4. 可选,客户端发送包含 SHOW name 查询字符串的 Query 消息。服务器端返回 DataRow 消息和 CommandComplete 消息。5. 可选,客户端发送包含 TIMELINE_HISTORY tli 查询字符串的 Query 消息。服务器端返回 RowDescription、DataRow 消息和 CommandComplete 消息。6. 可选,客户端发送包含 CREATE_REPLICATION_SLOT ... PHYSICAL ... 查询字符串的 Query 消息。服务器端返回 DataRow 消息和 CommandComplete 消息。7. 客户端发送包含 START_REPLICATION_SLOT ... PHYSICAL ... 查询字符串的 Query 消息。服务器端返回 CopyBothResponseDataRow 消息、多条包含 XLogData 内容的 CopyData 消息,可选的包含 Primary keepalive message(B:'k') 内容的 CopyData 消息。8. 可选,客户端可以向服务器端发送包含 Standby status update(F:'r') 内容的 CopyData 消息和 Hot Standby feedback message(F:'h') 内容的 CopyData 消息。9. 服务端向客户端返回两条 CommandComplete 消息。10. 可选,客户端发送包含 DROP_REPLICATION_SLOT ... 查询字符串的 Query 消息。服务器端返回 CommandComplete 消息。1. 客户端发起连接,向服务器端发送 StartupMessage 消息,包含参数 replication,值设置为 database。2. 服务器端接收到连接启动消息和 replication 参数,进入逻辑复制 WAL 发送者模式。3. 可选,客户端发送包含 IDENTIFY_SYSTEM 查询字符串的 Query 消息。服务器端返回 DataRow 消息和 CommandComplete 消息。4. 可选,客户端发送包含 SHOW name 查询字符串的 Query 消息。服务器端返回 DataRow 消息和 CommandComplete 消息。5. 可选,客户端发送包含 TIMELINE_HISTORY tli 查询字符串的 Query 消息。服务器端返回 RowDescription、DataRow 消息和 CommandComplete 消息。6. 客户端发送包含 START_REPLICATION_SLOT ... LOGICAL ... 查询字符串的 Query 消息。服务器端返回 CopyBothResponseDataRow 消息、多条包含 XLogData 内容的 CopyData 消息,可选的包含 Primary keepalive message(B:'k') 内容的 CopyData 消息。7. 可选,客户端可以向服务器端发送包含 Standby status update(F:'r') 内容的 CopyData 消息和 Hot Standby feedback message(F:'h') 内容的 CopyData 消息。8. 服务端向客户端返回两条 CommandComplete 消息。9. 可选,客户端发送包含 DROP_REPLICATION_SLOT ... 查询字符串的 Query 消息。服务器端返回 CommandComplete 消息。→ COPY-BOTH 的 BASE_BACKUP 模式1. 客户端发起连接,向服务器端发送 StartupMessage 消息,包含参数 replication。2. 服务器端接收到连接启动消息和 replication 参数,进入复制模式。3. 客户端发送包含 BASE_BACKUP ... 查询字符串的 Query 消息。服务器端返回 RowDescription、DataRow 消息和 CommandComplete 消息,记录起始位置。4. 服务器端发送一条 RowDescription 消息,然后为每个 tablespace 发送一条 DataRow 消息,后跟 CommandComplete 消息和 CopyOutResponse 消息。5. 服务器端然后开始复制数据,为每个 tablespace 发送多个 CopyData 消息和一个 CopyDone 消息。所有 tablespace 数据发送完成后,发送 CommandComplete 消息和 CopyOutResponse 消息。6. 服务器端最后发送 RowDescription、DataRow 消息和 CommandComplete 消息,记录复制结束位置。
以上就是 PostgreSQL Protocol v3 协议中流复制协议的全部内容介绍,主要应用于数据复制和主备场景,往期推荐可回看往期博客详情。欢迎大家关注、点赞、围观 😬