52.4. 流复制协议

为了启动流复制,前端在启动消息中发送replication参数。布尔值true指示后端进入 walsender 模式,在该模式下,可以发出一小组复制命令代替 SQL 语句。 walsender 模式下只能使用简单查询协议。启用log_replication_commands时,复制命令记录在服务器日志中。传递database作为值指示 walsender 连接到dbname参数中指定的数据库,这将允许该连接用于从该数据库进行逻辑复制。

为了测试复制命令,您可以通过 psql 或任何其他libpq-使用带有包括replication选项的连接字符串的工具进行复制连接,例如:

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

但是,使用pg_receivewal(用于物理复制)或pg_recvlogical(用于逻辑复制)通常更有用。

walsender 模式下接受的命令是:

  • 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 48.6)。
    • TEMPORARY

      • 指定此复制插槽是一个临时插槽。临时插槽不会保存到磁盘,并且会在发生错误或会话结束时自动删除。
    • RESERVE_WAL

      • 指定此物理复制插槽立即保留 WAL。否则,仅在从流复制 Client 端连接时保留 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 ]

    • 指示服务器从 WAL 位置* XXX/XXX 开始开始流式 WAL。如果指定了TIMELINE选项,则流将从时间轴 tli *开始;否则,将选择服务器的当前时间轴。服务器可以回复错误,例如,如果 WAL 的请求部分已经被回收。成功后,服务器将使用 CopyBothResponse 消息进行响应,然后开始将 WAL 流式传输到前端。

如果插槽的名称是通过* slot_name *提供的,它将在复制过程中进行更新,以便服务器知道备用数据库仍需要哪些 WAL 段,以及hot_standby_feedback是否在哪些事务上。

如果 Client 端请求的时间线不是最新的,而是服务器历史的一部分,则服务器将从该请求的开始点到服务器切换到另一个时间线的那一点,流式传输该时间线上的所有 WAL。如果 Client 端恰好在旧时间轴的末尾请求流传输,则服务器将立即使用 CommandComplete 进行响应,而无需进入 COPY 模式。

在不是最新时间线的时间线上流式传输所有 WAL 之后,服务器将退出 COPY 模式以结束流式传输。当 Client 端通过也退出 COPY 模式确认这一点时,服务器将发送一个包含一行和两列的结果集,以指示该服务器历史 Logging 的下一个时间轴。第一列是下一个时间轴的 ID(类型int8),第二列是发生切换的 WAL 位置(类型text)。通常,切换位置是流式传输的 WAL 的结尾,但是在极端情况下,服务器可以从旧时间轴发送一些 WAL,而该时间线本身在升级之前还没有重播。最后,服务器发送 CommandComplete 消息,并准备接受新命令。

WAL 数据作为一系列 CopyData 消息发送。 (这允许其他信息混合在一起;特别是如果服务器在开始流传输后遇到故障,则服务器可以发送 ErrorResponse 消息.)从服务器到 Client 端的每个 CopyData 消息的有效负载均包含以下格式之一的消息:

  • XLogData (B)

      • Byte1('w')

      • 将消息标识为 WAL 数据。

    • Int64

      • 此消息中 WAL 数据的起点。
    • Int64

      • 服务器上 WAL 的当前端。
    • Int64

      • 传输时服务器的系统时钟,从 2000-01-01 午夜起以毫秒为单位。
    • Byte n

      • WAL 数据流的一部分。

单个 WAL 记录永远不会拆分为两个 XLogData 消息。当 WAL 记录越过 WAL 页面边界并因此已经使用连续记录进行拆分时,可以在页面边界处对其进行拆分。换句话说,可以在不同的 XLogData 消息中发送第一个主 WAL 记录及其延续记录。

  • 主要的 Keepalive 讯息(B)

      • Byte1('k')

      • 将消息标识为发件人保持活动状态。

    • Int64

      • 服务器上 WAL 的当前端。
    • Int64

      • 传输时服务器的系统时钟,从 2000-01-01 午夜起以毫秒为单位。
    • Byte1

      • 1 表示 Client 端应尽快回复此消息,以避免超时断开连接。否则为 0.

接收过程可以随时使用以下消息格式之一(也位于 CopyData 消息的有效负载中)将答复发送回发送方:

  • 备用状态更新(F)

      • Byte1('r')

      • 将消息标识为收件人状态更新。

    • Int64

      • 接收到的最后一个 WAL 字节 1 的位置,并将其写入备用数据库中的磁盘。
    • Int64

      • 最后一个 WAL 字节 1 的位置刷新到备用数据库中的磁盘。
    • Int64

      • 备用数据库中应用的最后一个 WAL 字节 1 的位置。
    • Int64

      • 传输时 Client 端的系统时钟,以从 2000-01-01 午夜起的微秒为单位。
    • Byte1

      • 如果为 1,则 Client 端请求服务器立即回复此消息。这可用于 ping 服务器,以测试连接是否仍然健康。
  • 热备反馈消息(F)

      • Byte1('h')

      • 将消息标识为“热备”反馈消息。

    • Int64

      • 传输时 Client 端的系统时钟,以从 2000-01-01 午夜起的微秒为单位。
    • Int32

      • 备用数据库的当前全局 xmin,从任何复制插槽中排除 catalog_xmin。如果此值和随后的 catalog_xmin 均为 0,则将其视为不再在该连接上发送热备反馈的通知。以后的非零消息可能会重新启动反馈机制。
    • Int32

      • 备用数据库上的全局 xmin xid 的时期。
    • Int32

      • 备用数据库上所有复制插槽中最低的 catalog_xmin。如果备用数据库上不存在 catalog_xmin 或禁用了热备用反馈,则设置为 0.
    • Int32

      • 备用数据库上 catalog_xmin xid 的时期。
  • START_REPLICATION SLOT slot_name LOGICAL XXX/XXX [ ( option_name [ option_value ] [, ...] ) ]

    • 指示服务器从 WAL 位置* XXX/XXX *开始,开始流式传输 WAL 以进行逻辑复制。服务器可以回复错误,例如,如果 WAL 的请求部分已经被回收。成功后,服务器将使用 CopyBothResponse 消息进行响应,然后开始将 WAL 流式传输到前端。

CopyBothResponse 消息内的消息与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

      • 如果插槽处于活动状态,则此选项使命令 await,直到插槽变为非活动状态为止,而不是引发错误的默认行为。
  • 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 段。这将包括基本目录 tar 文件的pg_wal目录中开始和停止备份之间的所有文件。
    • NOWAIT

      • 默认情况下,备份将 await,直到最后一个所需的 WAL 段已归档为止;如果未启用日志归档,则备份将发出警告。指定NOWAIT将同时禁用 await 和警告,而由 Client 机负责确保所需的日志可用。
    • MAX_RATE rate

      • 限制(限制)每单位时间从服务器传输到 Client 端的最大数据量。预期的单位是每秒千字节。如果指定此选项,则该值必须等于零,或者必须在 32 kB 到 1 GB(包括 1K)之间。如果传递了零或未指定选项,则对传输没有任何限制。
    • TABLESPACE_MAP

      • 在名为tablespace_map的文件中包括有关目录pg_tblspc中存在的符号链接的信息。表空间 Map 文件包含目录pg_tblspc/中存在的每个符号链接名称以及该符号链接的完整路径。

开始备份时,服务器将首先发送两个普通结果集,然后发送一个或多个 CopyResponse 结果。

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

第二个普通结果集每个表空间都有一行。该行中的字段是:

  • spcoid ( oid )

    • 表空间的 OID;如果它是基本目录,则为 null。

    • spclocation ( text )

      • 表空间目录的完整路径;如果它是基本目录,则为 null。
    • size ( int8 )

      • 表空间的大概大小(如果已请求进度报告);否则为空。

在第二个常规结果集之后,将发送一个或多个 CopyResponse 结果,一个用于主数据目录,一个用于除pg_defaultpg_global之外的每个其他表空间。表空间内容的转储将为 CopyResponse 结果中的数据为 tar 格式(遵循 POSIX 1003.1-2008 标准中指定的“ ustar 交换格式”),但省略了该标准中指定的两个结尾的零块。 tar 数据完成后,将以与起始位置相同的格式发送最终普通结果集,其中包含备份的 WAL 结束位置。

数据目录和每个表空间的 tar 归档文件将包含目录中的所有文件,无论它们是 PostgreSQL 文件还是添加到同一目录的其他文件。唯一排除的文件是:

  • postmaster.pid

  • postmaster.opts

  • 在 PostgreSQL 服务器运行期间创建的各种临时文件和目录,例如以pgsql_tmp开头的任何文件或目录。

  • pg_wal,包括子目录。如果使用 WAL 文件运行备份,则将包含pg_wal的综合版本,但是它将仅包含备份工作所需的文件,而不包含其余内容。

  • pg_dynshmempg_notifypg_replslotpg_serialpg_snapshotspg_stat_tmppg_subtrans被复制为空目录(即使它们是符号链接)。

  • 跳过常规文件和目录以外的文件,例如符号链接(上述目录除外)和特殊设备文件。 (pg_tblspc中的符号链接得到维护.)

如果服务器上的基础文件系统支持,则设置所有者,组和文件模式。