53.4. 流复制协议

要启动流复制,前端在启动消息中发送replication参数。布尔值true(或者onyes1)告诉后端进入到物理复制的walsender模式,在其中可以发出一个小型的复制命令集合(见下文)而不是普通的SQL命令。

database作为replication参数的值传递会指示后端进入到逻辑复制的walsender模式,连接到dbname参数指定的数据库。在逻辑复制的walsender模式中,可以发出下文所示的复制命令以及普通的SQL命令。

在物理复制或者逻辑复制的walsender模式中,只能使用简单查询协议。

出于测试复制命令的目的,你可以通过psql或者任何使用libpq的工具使用包含replication选项的连接字符串建立一个复制连接,例如:

psql "dbname=postgres replication=database" -c "IDENTIFY_SYSTEM;"

不过更常用的是:pg_receivewal(对于物理复制)或者pg_recvlogical(对于逻辑复制)。

log_replication_commands被启用时,复制命令会被记录在服务器日志中。

在复制模式中可以接受的命令有:

IDENTIFY_SYSTEM

请求服务器标识它自己。服务器以一个行构成的结果集作为答复,其中包含四个域:

systemid (text)

标识该集簇的唯一的系统标识符。这可以被用来检查用于初始化后备机的基础备份是否来自于同一个集簇。

timeline (int4)

当前的时间线 ID。也对于检查后备机是否与主控机一致有用。

xlogpos (text)

当前的WAL刷写位置。用于得到一个在预写式日志中的已知位置作为流的开始位置。

dbname (text)

要连接到的数据库或者空。

SHOW name

请求服务器发送一个运行时参数的当前设置。这类似于SQL命令SHOW

name

运行时参数的名称。可用的参数在Chapter 19中。

TIMELINE_HISTORY tli

请求服务器将时间线tli的历史文件发送过来。服务器将以一行组成的结果集作为答复,其中包含两个域:

filename (text)

时间线历史文件的文件名,例如00000002.history

content (bytea)

时间线历史文件的内容。

CREATE_REPLICATION_SLOT slot_name [ TEMPORARY ] { PHYSICAL [ RESERVE_WAL ] | LOGICAL output_plugin [ EXPORT_SNAPSHOT | NOEXPORT_SNAPSHOT | USE_SNAPSHOT ] }

创建一个物理的或者逻辑的复制槽。更多关于复制槽的内容请见 Section 26.2.6

slot_name

要创建的槽的名称。必须是一个合法的复制槽名称(见 Section 26.2.6.1)。

output_plugin

被用于逻辑解码的输出插件的名称(见 Section 49.6)。

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)

被这个命令导出的快照的标识符。该快照一直是有效的,直到在这个连接中执行了新的命令或者该复制连接被关闭。如果被创建的槽是物理槽,则为空。

output_plugin (text)

新创建的复制槽使用的输出插件的名称。如果被创建的槽是物理槽,则为空。

START_REPLICATION [ SLOT slot_name ] [ PHYSICAL ] XXX/XXX [ TIMELINE tli ]

指示服务器开始启动流WAL,从 WAL 位置XXX/XXX开始。如果TIMELINE选项被指定,流传送会在时间线tli上开始,否则会选择服务器的当前时间线。服务器可以回复一个错误,例如如果被请求的WAL节已经被回收了。如果成功,服务器将会响应一个CopyBothResponse消息,并且然后开始以流的方式把WAL传送给前端。

如果通过slot_name提供了一个槽的名称,它将被更新复制进度,这样该服务器知道哪些 WAL 段以及哪些事务(如果hot_standby_feedback为打开)仍然被后备机所需要。

如果客户端请求一个并非最新的时间线,但是属于服务器历史的一部分,服务器将会把该时间线上从请求点开始的所有WAL以流式传送,一直到服务器切换到另外一个时间线的点。如果客户端请求在一个老的时间线末尾进行流传送,服务器将在不进入COPY模式的情况下立即响应CommandComplete。

在流传送完一个非最新时间线上所有的WAL之后,服务器将会通过退出COPY模式来结束流。当客户端认识到这一点并也退出COPY模式时,服务器会发送一个包含一行两列的结果集,以指示在该服务器历史中的下一个时间线。第一列是下一个时间线的 ID(类型int8),而第二列是发生切换的 WAL 位置(类型text)。通常,切换位置是被流传送的WAL的末尾,但是在很少的情况下服务器会从旧的时间线中发送一些WAL,而该时间线是服务器本身在提示之前还没有重放的。最后,服务器发送CommandComplete消息,并且做好准备接受一个新的命令。

WAL数据以一系列CopyData消息的形式被发送(这允许其他信息穿插其中,特别是服务器可以在开始流传送后遇到失败时发送一个ErrorResponse消息)。每个从服务器到客户端的CopyData消息承载了一个下列格式之一的消息:

XLogData (B)

Byte1('w')

标识该消息是WAL数据。

Int64

在消息中WAL数据的起始点。

Int64

服务器上WAL的当前终点。

Int64

在传送时服务器的系统时钟,以从2000-01-01午夜开始的微妙计。

Byten

WAL数据流的一节。

一个WAL记录绝不会被分割到两个XLogData消息。如果一个WAL记录跨越了一个WAL页面的边界,并且因此已经被使用连续的记录分割,它可以在页面边界被分割。换句话说,第一个主要WAL记录和它的后续记录可以在不同的XLogData消息中被发送。

主要存活消息 (B)

Byte1('k')

标识该消息是一个发送者存活消息。

Int64

服务器上WAL的当前终点。

Int64

在传送时服务器的系统时钟,以从2000-01-01午夜开始的微妙计。

Byte1

1表示客户端应该尽快回复该消息,以避免连接超时。否则为0。

接收进程可以在任何时候给发送者发送回复,回复可以使用下列消息格式之一(也在CopData消息中使用):

后备机状态更新 (F)

Byte1('r')

标识该消息是一个接收者状态更新。

Int64

接收到并且写入到后备机磁盘的最后一个WAL比特的位置+1。

Int64

被刷入到后备机磁盘的最后一个WAL比特的位置+1。

Int64

被应用在后备机上的最后一个WAL比特的位置+1。

Int64

在传送时客户端的系统时钟,以从2000-01-01午夜开始的微妙计。

Byte1

如果为1,客户端要求服务器马上回复这个消息。这可以被用来ping服务器以测试连接是否仍然完好。

热备机反馈消息 (F)

Byte1('h')

标识该消息是一个热备机反馈消息。

Int64

在传送时客户端的系统时钟,以从2000-01-01午夜开始的微妙计。

Int32

后备机的当前全局xmin,排除来自任何复制槽的catalog_xmin。如果这个值和接下来的catalog_xmin都为0,这会被当作一个通知表示在这个连接上将不会再发送热备反馈。后来的非0消息将重新启动反馈机制。

Int32

后备机上全局xmin事务ID的世代。

Int32

后备机上任意复制槽中的最小catalog_xmin。如果在后备机上不存在catalog_xmin或者热备反馈被禁用,这个值被设置为0。

Int32

后备机上全局catalog_xmin事务ID的世代。

START_REPLICATION SLOT slot_name LOGICAL XXX/XXX [ ( option_name [ option_value ] [, ...] ) ]

指示服务器为逻辑复制开始流式传送 WAL,从 WAL 位置XXX/XXX开始。服务器可以回复一个错误,例如如果请求的 WAL 小节已经回环。如果成功,服务器会响应一个 CopyBothResponse 消息,并且接着开始流失传送 WAL 给前端。

消息内部的消息与START_REPLICATION ... PHYSICAL中记录的格式相同。

与选中槽关联的输出插件被用来处理流的输出。

SLOT slot_name

要从哪个槽流式传送改变。这个参数是必须的,并且必须对应于一个现有的用LOGICAL模式的CREATE_REPLICATION_SLOT创建的逻辑复制槽。

XXX/XXX

要开始流传送的 WAL 位置。

option_name

一个传递给该槽的逻辑解码插件的选项的名称。

option_value

字符串常量形式的选项值,与前面指定的选项关联。

DROP_REPLICATION_SLOT slot_name [ WAIT ]

删除一个复制槽,释放任何保留的服务器端资源。如果该槽是一个在不同于walsender所连接的数据库中创建的逻辑槽,这个命令会失败。

slot_name

要删除的槽的名称。

WAIT

如果槽正处于活跃状态,这个选项会导致命令等待,直到槽变得不活跃,而不是像默认行为那样直接报错。

BASE_BACKUP [ LABEL 'label' ] [ PROGRESS ] [ FAST ] [ WAL ] [ NOWAIT ] [ MAX_RATE rate ] [ TABLESPACE_MAP ]

指示服务器开始流传送一个基础备份。在备份开始之前系统将自动被置于备份模式,而在备份结束时会自动被退出备份模式。可以接受下列选项:

LABEL 'label'

设置备份的标签。如果没有指定,将会使用base backup作为标签。标签的引号规则和standard_conforming_strings开启时标准SQL字符串的一样。

PROGRESS

请求用以生成一个进度报告的信息。这将送回位于每个表空间头部的一个近似大小,它可以被用于计算流还有多久才能被完成。它通过在传输开始之前枚举所有文件大小来计算,并且可能会对性能产生一种负面影响 -- 特别情况下它可能会在流传送第一个数据之前就耗费很长时间。因为数据库文件可能在备份期间改变,这个大小只是近似的并且可能在近似计算和发送真正的文件之间增长或者收缩。

FAST

请求一个快速检查点。

WAL

在备份中包含必需的WAL段。这将把开始和停止备份之间的所有文件包括在base目录tar文件中的pg_wal目录中。

NOWAIT

默认情况下,备份会等待直到最后一个要求的 WAL 段被归档,或者当日至归档被禁用时发出一个警告。指定NOWAIT会禁用等待和警告,而让客户端负责确保所要求的日志是可用的。

MAX_RATE rate

单位时间内从服务器传输到客户端的最大数据量限制。期望的单位是千字节每秒。如果指定了这个选项,值必须等于零或者位于 32 kB到 1 GB(包括)范围之间。如果 0 被传入或者没有指定该选项,对于传输将没有限制。

TABLESPACE_MAP

在名为tablespace_map的文件中包括有关pg_tblspc目录中存在的符号链接的信息。这个表空间映射文件包括了在目录pg_tblspc中存在的每一个符号链接的名字以及它的完整路径。

NOVERIFY_CHECKSUMS

默认情况下,如果启用了校验码,在基础备份期间会验证校验码。指定NOVERIFY_CHECKSUMS可以禁用这种验证。

当备份被启动,服务器将首先发送两个普通结果集,后面会跟着一个或多个CopyResponse结果。

第一个普通结果集在一行两列中包含了备份的起始位置。第一列包含使用XLogRecPtr格式给出的开始位置,第二列包含相应的时间线ID。

第二个普通结果集中为每一个表空间都有一行。行中的域有:

spcoidoid

表空间的 OID,如果是base目录则为空。

spclocationtext

表空间目录的完整路径,如果是base目录则为空。

sizeint8

如果进度报告被请求,这里是表空间的近似大小,否则为空。

在第二个普通结果集之后,一个或多个CopyResponse结果将被发送,一个用于主数据目录而对每一个除pg_defaultpg_global之外的额外表空间也会有一个。CopyResponse结果中的数据将会使一个tar格式(遵循POSIX 1003.1-2008标准中指定的ustar交换格式)的表空间内容转储,不过标准中定义的两个拖尾全0块将被忽略。在tar数据完成后,一个最终普通结果集将被发送,包含了备份的WAL结束位置,格式与起始位置相同。

用于数据目录和每个表空间的tar归档将包含目录中的所有文件,不管它们是否为PostgreSQL文件或者是被加入的其他文件。唯一被排除的文件是:

  • postmaster.pid

  • postmaster.opts

  • pg_internal.init(在多个目录中都有)

  • 在PostgreSQL服务器操作过程中创建的各种临时文件和目录,例如任何以pgsql_tmp开头的文件或目录以及临时关系。

  • 不做日志的关系,init分支除外,恢复时重建(空的)不做日志关系时需要它。

  • pg_wal及其子目录。如果备份运行时要求包括WAL文件,一个pg_wal的合成版本将被包括进来,但是只会包含那些备份工作必需的文件,而不是包含剩下的内容。

  • pg_dynshmempg_notifypg_replslotpg_serialpg_snapshotspg_stat_tmp以及 pg_subtrans会被拷贝为空目录(即使它们是符号链接)。

  • 跳过除常规文件和目录之外的其他文件,例如符号链接(不同于上面所列出的目录)和特殊设备文件。(pg_tblspc中的符号链接会被保留)。

如果服务器上的底层文件系统支持,所有者、组合文件模式都会被设置。