本期将重点介绍流复制,因篇幅较长,我们会分上下两个篇章展开深度介绍。
上篇:流复制介绍、复制命令及逻辑流复制协议。
下篇:扩展查询及消息格式、流复制交互流程。
欢迎大家关注、点赞、围观 😬
流复制介绍
COPY-IN 模式
数据从客户端传输到服务器端。COPY-OUT 模式
数据从服务器端传输到客户端。COPY-BOTH 模式
服务器端和客户端数据可以双向传输。
复制命令
Shell
psql "dbname=postgres replication=database" -c "IDENTIFY_SYSTEM;"
systemid (text):标识集群的唯一系统标识符。使用该字段可以检查用于初始化待命状态的基础备份是否来自同一集群。 timeline (int4):当前时间线 ID。也可以用于检查待命状态是否与主集群状态一致。 xlogpos (text):当前 WAL flush 位置。用于在 WAL 中获取可以启动流的已知位置。 dbname (text):连接的目标数据库。可以为 null。
TIMELINE_HISTORY tli
filename (text):时间线历史文件的文件名,例如 00000002.history。 content (text):时间线历史文件的内容。
CREATE_REPLICATION_SLOT slot_name [ TEMPORARY ] { PHYSICAL [ RESERVE_WAL ] | LOGICAL output_plugin [ EXPORT_SNAPSHOT | NOEXPORT_SNAPSHOT | USE_SNAPSHOT ] }
slot_name:要创建的插槽的名称。必须是有效的复制插槽名称,它可以包含小写字母、数字和下划线。 output_plugin:用于逻辑解码的输出插件的名称。详情可以参考逻辑解码输出插件。 TEMPORARY:指定此复制插槽为临时插槽。临时插槽不会保存到磁盘,并且会在出现错误或会话结束时自动删除。 RESERVE_WAL:指定此物理复制插槽立即保留 WAL。否则,WAL 仅在从流复制客户端连接时保留。 EXPORT_SNAPSHOT, NOEXPORT_SNAPSHOT, USE_SNAPSHOT:决定如何处理在逻辑插槽初始化期间创建的快照。EXPORT_SNAPSHOT 是默认值,它将导出快照以便在其他会话中使用。此选项不能在事务内部使用。USE_SNAPSHOT 将为执行该命令的当前事务使用快照。此选项必须在事务中使用,并且 CREATE_REPLICATION_SLOT 必须是该事务中运行的第一个命令。最后,NOEXPORT_SNAPSHOT 将正常使用快照进行逻辑解码,但不会对其执行任何其他操作。
slot_name (text):新创建的复制插槽的名称。 consistent_point (text):插槽变得一致的 WAL 位置。这是可以在此复制插槽上启动流的最早位置。 snapshot_name (text):命令导出的快照的标识符。在该连接上执行新命令或关闭复制连接之前,快照一直有效。如果创建的插槽是物理插槽,则为 null。 output_plugin (text):新创建的复制插槽使用的输出插件的名称。如果创建的插槽是物理插槽,则为 null。
START_REPLICATION [ SLOT slot_name ] [ PHYSICAL ] XXX/XXX [ TIMELINE tli ]
Byte1('w'):将消息标识为 WAL 数据。 Int64:此消息中 WAL 数据的起点。 Int64:服务器上 WAL 的当前结束。 Int64:服务器在传输时的系统时钟,自 2000-01-01 午夜起以微秒为单位。 Byten:WAL 数据流的部分数据。单个 WAL 记录永远不会拆分为两条 XLogData 消息。当 WAL 记录越过 WAL 页面边界,因此已经使用连续记录进行拆分时,可以在页面边界进行拆分。也就是说,第一个主 WAL 记录及其后续记录可以在不同的 XLogData 消息中发送。
Byte1('k'):将消息标识为 sender keepalive。 Int64:服务器上 WAL 的当前结束。 Int64:服务器在传输时的系统时钟,自 2000-01-01 午夜起以微秒为单位。 Byte1:1,表示客户端应尽快回复此消息,以避免超时断开连接;否则为 0。
Byte1('r'):将消息标识为接收方状态更新。 Int64:在备机接收并写入磁盘的最后一个 WAL 字节 + 1 的位置。 Int64:在备机刷新到磁盘的最后一个 WAL 字节 + 1 的位置。 Int64:在备机应用的最后一个 WAL 字节 + 1 的位置。 Int64:传输时客户端的系统时钟,自 2000-01-01 午夜起以微秒为单位。 Byte1:1,客户端请求服务器立即回复此消息,可以用来 ping 服务器以测试连接是否仍然正常。
Byte1('h'):将消息标识为热备反馈消息。 Int64:传输时客户端的系统时钟,自 2000-01-01 午夜起以微秒为单位。 Int32:备机的当前全局 xmin,不包括任何复制插槽中的 catalog_xmin。如果 xmin 和下面的 catalog_xmin 都为 0,则将被视为不再在此连接上发送热备反馈的通知。稍后的非 0 消息可以重新启动反馈机制。 Int32:备机的全局 xmin xid 的 epoch。 Int32:备机复制插槽中最低的 catalog_xmin。如果备机上不存在 catalog_xmin,或者热备反馈被禁用,则设置为 0。 Int32:备机的 catalog_xmin xid 的 epoch。
START_REPLICATION SLOT slot_name LOGICAL XXX/XXX [ ( option_name [ option_value ] [, ...] ) ]
(滑动查看完完整代码)
START_REPLICATION SLOT slot_name LOGICAL XXX/XXX [ ( option_name [ option_value ] [, ...] ) ]
SLOT slot_name:要变更的流式传输的插槽名称。此参数是必需的,并且必须与在 LOGICAL 模式下使用 CREATE_REPLICATION_SLOT 创建的现有逻辑复制插槽相对应。 XXX/XXX:开始流式传输的 WAL 位置。 option_name:传递到插槽的逻辑解码插件的选项的名称。 option_value:与指定选项关联的字符串常量形式的可选值。
DROP_REPLICATION_SLOT slot_name [ WAIT ]
slot_name:要删除的插槽的名称。 WAIT:如果插槽处于活动状态,此选项会导致命令等待,直到它变为非活动状态,而不是引发错误的默认行为。
BASE_BACKUP [ LABEL 'label' ] [ PROGRESS ] [ FAST ] [ WAL ] [ NOWAIT ] [ MAX_RATE rate ] [ TABLESPACE_MAP ] [ NOVERIFY_CHECKSUMS ] [ MANIFEST manifest_option ] [ MANIFEST_CHECKSUMS checksum_algorithm ]
LABEL 'label':设置备份的标签。如果未指定,则将使用 base backup 的备份标签。标签的引用规则与打开 standard_conforming_strings 的标准 SQL 字符串相同。
PROGRESS:请求生成进度报告所需的信息。这将在每个表空间的头中发送回一个近似大小,该大小可用于计算流复制的执行进度。这是通过在传输开始之前遍历一次所有文件大小来计算的,因此可能会对性能产生负面影响。特别是,可能需要更长的时间才能开始流式传输第一个数据。由于数据库文件在备份过程中可能会发生变化,因此大小只是近似值,在近似值和发送实际文件大小之间可能会增长和减少。
FAST:请求快速检查点。
WAL:在备份中包括必要的 WAL 段。这将包括基准目录 tar 文件的 pg_wal 目录中启动和停止备份之间的所有文件。
NOWAIT:默认情况下,备份将等待最后一个所需的 WAL 段存档,或者如果未启用日志存档,则会发出警告。指定 NOWAIT 将禁用等待和警告,让客户端负责确保所需的日志可用。
MAX_RATE rate:限制每单位时间从服务器传输到客户端的最大数据量。预期的单位是 KB/s(千字节每秒)。如果指定了此选项,则该值必须等于零,或者必须在 32 kB 到 1 GB(包括 32 kB 和 1 GB)的范围内。如果指定选项为 0 或未指定选项,则不会对传输施加任何限制。
TABLESPACE_MAP:在名为 tablespace_map 的文件中包含有关目录 pg_tblspc 中存在的符号链接的信息。表空间映射文件包括目录 pg_tblspc/ 中存在的每个符号链接名称以及该符号链接的完整路径。
NOVERIFY_CHECKSUMS:默认情况下,如果启用了校验和,则会在基础备份期间验证校验和。指定 NOVERIFY_CHECKSUMS 将禁用此验证。
MANIFEST manifest_option:如果指定此选项的值为 yes 或 force-encode,则会创建备份清单并将其与备份一起发送。清单是备份中存在的每个文件的列表,但可能包括的任何 WAL 文件除外。它还存储每个文件的大小、上次修改时间以及可选的校验和。force-encode 的值强制所有文件名进行十六进制编码;否则,仅对名称为非 UTF8 八位位组序列的文件执行这种类型的编码。force-encode 主要用于测试目的,以确保读取备份清单的客户端能够处理这种情况。为了与以前的版本兼容,默认值为 MANIFEST 'no'。
MANIFEST_CHECKSUMS checksum_algorithm:指定应用于备份清单中包含的每个文件的校验和算法。目前,可用的算法有 NONE、CRC32C、SHA224、SHA256、SHA384 和 SHA512。默认值为 CRC32C。
spcoid (oid):表空间的 OID,如果是基准目录,则为 null。 spclocation (text):表空间目录的完整路径,如果是基准目录,则为 null。 size (int8):如果请求了进度报告,则值为表空间的大致大小,以 KB(1024 字节)为单位;否则为 null。
postmaster.pid postmaster.opts pg_internal.init:在多个目录中存在。 PostgreSQL 服务器运行过程中创建的各种临时文件和目录,例如以 pgsql_tmp 开头的任何文件或目录以及临时关系表。 未标记的关系表。除了在恢复时重新创建(空的)未标记关系需要的初始化复制文件。 pg_wal,包括子目录。如果备份是在包含 WAL 文件的情况下运行的,则会包含 pg_wal 的合成版本,但它只包含备份工作所需的文件,而不包含其余内容。 pg_dynshmem、pg_notify、pg_replslot、pg_serial、pg_snapshots、pg_stat_tmp 和 pg_subtrans 被复制为空目录(即使它们是符号链接)。 跳过常规文件和目录以外的文件,如符号链接(上面列出的目录除外)和特殊设备文件。pg_tblspc 中的符号链接将得到保留维护。
逻辑流复制协议
proto_version:协议版本。目前支持版本 1 和版本 2。版本 2 仅支持服务器版本 14 及更高版本,并且它允许对正在进行的大型事务进行流式传输。 publication_names:要订阅(接收更改)的发布名称的逗号分隔列表。各个发布名称被视为标准对象名称,并且可以根据需要引用相同的名称。
Begin
Byte1('B'):将消息标识为开始消息。
Int64:事务的最终 LSN。
Int64:事务的提交时间戳。该值以 PostgreSQL epoch(2000-01-01)以来的微秒为单位。
Int32:事务的 Xid。
Message
Byte1('M'):将消息标识为逻辑解码消息。
Int32:事务的 Xid(仅用于流式事务)。此字段自协议版本 2 起可用。
Int8:flags。0,表示没有标志;1 表示逻辑解码消息是事务性的。
Int64:逻辑解码消息的 LSN。
String:逻辑解码消息的前缀。
Int32:内容的长度。
Byten:逻辑解码消息的内容。
Commit
Byte1('C'):将消息标识为提交消息。
Int8:flags。当前未使用(必须为 0)。
Int64:提交的 LSN。
Int64:事务的结束 LSN。
Int64:事务的提交时间戳。该值以 PostgreSQL epoch(2000-01-01)以来的微秒为单位。
Origin
注意:在一个事务中可以有多个 Origin 消息。
Byte1('O'):将消息标识为 Origin 消息。
Int64:源服务器上提交的 LSN。
String:Origin 名称。
Relation
Byte1('R'):将消息标识为 Relation 消息。
Int32:事务的 Xid(仅用于流式事务)。此字段自协议版本 2 起可用。
Int32:Relation 的 ID。
String:命名空间(pg_catalog 命名空间为空字符串)。
String:Relation 名称。
Int8:Relation 的副本标识设置(与 pg_class 中的 relreplident 相同)。
Int16:列数量。
接下来,每个列(生成的列除外)都会显示以下消息部分:
Int8:列的标志。当前可以为 0 表示没有标志,也可以为 1 表示将列标记为 key 的一部分。
String:列名称。
Int32:列的数据类型的 ID。
Int32:列的类型修饰符(atttypmod)。
Type
Byte1('Y'):将消息标识为类型消息。
Int32:事务的 Xid(仅用于流式事务)。此字段自协议版本 2 起可用。
Int32:数据类型的 ID。
String:命名空间(pg_catalog 命名空间为空字符串)。
String:数据类型的名称。
Insert
Byte1('I'):将消息标识为插入消息。
Int32:事务的 Xid(仅用于流式事务)。此字段自协议版本 2 起可用。
Int32:与关系消息中的 ID 对应的关系的 ID。
Byte1('N'):将以下 TupleData 消息标识为新元组。
TupleData:表示新元组内容的 TupleData 消息部分。
Update
Byte1('U'):将消息标识为更新消息。
Int32:事务的 Xid(仅用于流式事务)。此字段自协议版本 2 起可用。
Int32:与关系消息中的 ID 对应的关系的 ID。
Byte1('K'):将以下 TupleData 子消息标识为键。此字段是可选的,仅当更新操作更改了 REPLICA IDENTITY 索引中任何列中的数据时才出现。
Byte1('O'):将以下 TupleData 子消息标识为旧元组。此字段是可选的,仅当发生更新的表的 REPLICA IDENTITY 设置为 FULL 时才存在。
TupleData:表示旧元组或主键内容的 TupleData 消息部分。仅当存在前一个 O 或 K 部分时才存在。
Byte1('N'):将以下 TupleData 消息标识为新元组。
TupleData:表示新元组内容的 TupleData 消息部分。
更新消息可能包含 K 消息部分或 O 消息部分,也可能两者都不包含,但决不能同时包含两者。
Delete
Byte1('D'):将消息标识为删除消息。
Int32:事务的 Xid(仅用于流式事务)。此字段自协议版本 2 起可用。
Int32:与关系消息中的 ID 对应的关系的 ID。
Byte1('K'):将以下 TupleData 子消息标识为键。如果发生删除的表使用了 REPLICA IDENTITY 的索引,则会出现此字段。
Byte1('O'):将以下 TupleData 消息标识为旧元组。如果发生删除的表的 REPLICA IDENTITY 设置为 FULL,则会出现此字段。
TupleData:TupleData 消息部分表示旧元组或主键的内容,具体取决于前一个字段。
Delete 消息可能包含 K 消息部分或 O 消息部分,但决不能同时包含这两个部分。
Truncate
Byte1('T'):将消息标识为 Truncate 消息。
Int32:事务的 Xid(仅用于流式事务)。此字段自协议版本 2 起可用。
Int32:关系的数量。
Int8:TRUNCATE 的选项位:1 用于 CASCADE,2 用于 RESTART IDENTITY。
Int32:与关系消息中的 ID 对应的关系的 ID。对于每个关系,都会重复此字段。
自协议版本 2 以来,以下消息(流启动、流停止、流提交和流中止)可用。
11. Stream Start
Byte1('A'):将消息标识为流中止消息。
Int32:事务的 Xid。
Int32:子事务的 Xid(对于顶级事务,将和事务的 Xid 相同)。
11. Stream Stop
Byte1('E'):将消息标识为流停止消息。
Byte1('c'):将消息标识为流提交消息。
Int32:事务的 Xid。
Int8:标识。当前未使用(必须为 0)。
Int64:提交的 LSN。
Int64:事务的结束 LSN。
Int64:事务的提交时间戳。该值以 PostgreSQL epoch(2000-01-01)以来的微秒为单位。
Byte1('A'):将消息标识为流中止消息。
Int32:事务的 Xid。
Int8:值 1 表示这是该 XID 的第一个流段,0 表示任何其他流段。
14. 以下消息部分由上述消息共享:
TupleData,Int16:列数。接下来,每列(生成的列除外)都会显示以下子消息之一:
Byte1('n'):将数据标识为 NULL 值。
Byte1('u'):标识未更改的 TOASTed 值(不发送实际值)。
Byte1('t'):将数据标识为文本格式的值。
Byte1('b'):将数据标识为二进制格式的值。
Int32:列值的长度。
Byten:列的值,可以是二进制格式,也可以是文本格式。(如前面格式字节中所指定的)。n 是上述列值长度。
往期推荐