2025年9月25日: PostgreSQL 18 发布!
支持的版本: 当前 (18) / 17 / 16 / 15 / 14 / 13
开发版本: devel
不支持的版本: 12 / 11 / 10 / 9.6 / 9.5 / 9.4 / 9.3 / 9.2 / 9.1 / 9.0

54.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 (int8)

当前时间线 ID。也用于检查备用服务器是否与主服务器一致。

xlogpos (text)

当前的 WAL flush 位置。用于获取写入日志中一个已知的位置,以便从中开始流式传输。

dbname (text)

正在连接的数据库,或为 null。

SHOW name #

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

name

运行时参数的名称。可用参数在 第 19 章 中有详细说明。

TIMELINE_HISTORY tli #

请求服务器发送时间线 tli 的时间线历史文件。服务器会回复一个包含两个字段的单行结果集。虽然字段被标记为 text,但它们实际上返回原始字节,不进行编码转换。

filename (text)

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

content (text)

时间线历史文件的内容。

CREATE_REPLICATION_SLOT slot_name [ TEMPORARY ] { PHYSICAL | LOGICAL output_plugin } [ ( option [, ...] ) ] #

创建物理或逻辑复制槽。有关复制槽的更多信息,请参阅 26.2.6 节“复制槽”

slot_name

要创建的槽的名称。必须是有效的复制槽名称(参见 26.2.6.1 节“查询和操作复制槽”)。

output_plugin

用于逻辑解码的输出插件的名称(参见 47.6 节“逻辑解码输出插件”)。

TEMPORARY

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

支持以下选项:

TWO_PHASE [ boolean ]

如果为 true,此逻辑复制槽支持两阶段提交的解码。使用此选项时,会解码并传输与两阶段提交相关的命令,如 PREPARE TRANSACTIONCOMMIT PREPAREDROLLBACK PREPARED。事务将在 PREPARE TRANSACTION 时进行解码和传输。默认为 false。

RESERVE_WAL [ boolean ]

如果为 true,此物理复制槽会立即预留 WAL。否则,WAL仅在连接到流复制客户端时预留。默认为 false。WAL只有在流复制客户端连接时才预留。默认为 false。

SNAPSHOT { 'export' | 'use' | 'nothing' }

决定在初始化逻辑槽时创建的快照应如何处理。'export'(默认值)会将快照导出供其他会话使用。此选项不能在事务内使用。'use' 会将快照用于当前执行命令的事务。此选项必须在事务中使用,并且 CREATE_REPLICATION_SLOT 必须是该事务中运行的第一个命令。最后,'nothing' 将像往常一样仅将快照用于逻辑解码,但不会对其执行任何其他操作。

FAILOVER [ boolean ]

如果为 true,则启用该槽以同步到备用服务器,以便在故障转移后可以恢复逻辑复制。默认为 false。

响应此命令,服务器将发送一个单行结果集,包含以下字段:

slot_name (text)

新创建的复制槽的名称。

consistent_point (text)

槽变得一致的 WAL 位置。这是在此复制槽上进行流式传输的最早可能的起始位置。

snapshot_name (text)

命令导出的快照的标识符。快照有效,直到在此连接上执行新命令或复制连接关闭。如果创建的槽是物理槽,则为 null。

output_plugin (text)

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

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

为了兼容旧版本,CREATE_REPLICATION_SLOT 命令的这个备用语法仍然受支持。

ALTER_REPLICATION_SLOT slot_name ( option [, ...] ) #

更改复制槽的定义。有关复制槽的更多信息,请参阅 26.2.6 节“复制槽”。此命令目前仅支持逻辑复制槽。

slot_name

要更改的槽的名称。必须是有效的复制槽名称(参见 26.2.6.1 节“查询和操作复制槽”)。

支持以下选项:

TWO_PHASE [ boolean ]

如果为 true,此逻辑复制槽支持两阶段提交的解码。使用此选项时,会解码并传输与两阶段提交相关的命令,如 PREPARE TRANSACTIONCOMMIT PREPAREDROLLBACK PREPARED。事务将在 PREPARE TRANSACTION 时进行解码和传输。

FAILOVER [ boolean ]

如果为 true,则启用该槽以同步到备用服务器,以便在故障转移后可以恢复逻辑复制。

READ_REPLICATION_SLOT slot_name #

读取与复制槽相关的一些信息。如果复制槽不存在,则返回一个具有 NULL 值的元组。此命令目前仅支持物理复制槽。

响应此命令,服务器将返回一个单行结果集,包含以下字段:

slot_type (text)

复制槽的类型,为 physicalNULL

restart_lsn (text)

复制槽的 restart_lsn

restart_tli (int8)

restart_lsn 关联的时间线 ID,遵循当前时间线历史。

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 开启)哪些事务。

如果客户端请求的时间线不是最新的,但属于服务器历史的一部分,服务器将从请求的起始点开始流式传输该时间线上的所有 WAL,直到服务器切换到另一条时间线为止。如果客户端请求在旧时间线的结束点进行流式传输,服务器将完全跳过 COPY 模式。

在流式传输完非最新时间线上的所有 WAL 后,服务器将通过退出 COPY 模式来结束流式传输。当客户端通过也退出 COPY 模式来确认这一点后,服务器会发送一个包含一行两列的结果集,指示此服务器历史中的下一个时间线。第一列是下一个时间线的 ID(类型 int8),第二列是发生切换的 WAL 位置(类型 text)。通常,切换位置是流式传输的 WAL 的结束位置,但也有特殊情况,服务器可能会发送一些它自己尚未重放的旧时间线的 WAL,然后再提升。

WAL 数据作为一系列 CopyData 消息发送;有关详细信息,请参阅 54.6 节“消息数据类型”54.7 节“消息格式”。(这允许混合其他信息;特别是,服务器可以在开始流式传输后发送一个 ErrorResponse 消息,如果遇到失败。)从服务器到客户端的每个 CopyData 消息的有效负载都包含以下格式之一的消息:

XLogData (B) #
Byte1('w')

标识消息为 WAL 数据。

Int64

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

Int64

服务器上的当前 WAL 结束位置。

Int64

服务器的系统时钟在传输时的值,表示自 2000-01-01 午夜以来的微秒数。

Byten

WAL 数据流的一部分。

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

Primary keepalive message (B) #
Byte1('k')

标识消息为发送方 keepalive。

Int64

服务器上的当前 WAL 结束位置。

Int64

服务器的系统时钟在传输时的值,表示自 2000-01-01 午夜以来的微秒数。

Byte1

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

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

Standby status update (F) #
Byte1('r')

标识消息为接收方状态更新。

Int64

在备用服务器上接收并写入磁盘的最后一个 WAL 字节 + 1 的位置。

Int64

在备用服务器上刷新到磁盘的最后一个 WAL 字节 + 1 的位置。

Int64

在备用服务器上应用(applied)的最后一个 WAL 字节 + 1 的位置。

Int64

客户端系统时钟在传输时的值,表示自 2000-01-01 午夜以来的微秒数。

Byte1

如果为 1,客户端请求服务器立即回复此消息。这可以用来 ping 服务器,以测试连接是否仍然健康。

Hot standby feedback message (F) #
Byte1('h')

标识消息为热备用反馈消息。

Int64

客户端系统时钟在传输时的值,表示自 2000-01-01 午夜以来的微秒数。

Int32

备用服务器的当前全局 xmin,不包括任何复制槽的 catalog_xmin。如果此值和后面的 catalog_xmin 均为 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 ] [, ...] ) ] #

指示服务器开始流式传输逻辑复制的 WAL,从 WAL 位置 XXX/XXX 或槽的 confirmed_flush_lsn(参见 53.20 节“pg_replication_slots”)开始,取两者中较大的一个。这种行为使得客户端更容易在没有数据需要处理时避免更新其本地 LSN 状态。但是,从与请求不同的 LSN 开始可能无法捕获某些类型的客户端错误;因此,客户端在发出 START_REPLICATION 之前可能希望检查 confirmed_flush_lsn 是否与其预期值匹配。

服务器可能会回复错误,例如,如果槽不存在。成功时,服务器会响应一个 CopyBothResponse 消息,然后开始将 WAL 流式传输到前端。

CopyBothResponse 消息内的消息格式与为 START_REPLICATION ... PHYSICAL 记录的格式相同,包括两个 CommandComplete 消息。

所选槽关联的输出插件用于处理流式传输的输出。

SLOT slot_name

要从中流式传输更改的槽的名称。此参数是必需的,并且必须对应一个使用 CREATE_REPLICATION_SLOTLOGICAL 模式下创建的现有逻辑复制槽。

XXX/XXX

开始流式传输的 WAL 位置。

option_name

传递给槽的逻辑解码输出插件的选项的名称。有关标准(pgoutput)插件接受的选项,请参阅 54.5 节“逻辑流复制协议”

option_value

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

DROP_REPLICATION_SLOT slot_name [ WAIT ] #

删除复制槽,释放任何服务器端预留的资源。

slot_name

要删除的槽的名称。

WAIT

此选项使命令在槽处于活动状态时等待,直到其变为非活动状态,而不是默认的引发错误行为。

UPLOAD_MANIFEST #

上传备份清单,为进行增量备份做准备。

BASE_BACKUP [ ( option [, ...] ) ] #

指示服务器开始流式传输基础备份。在开始备份之前,系统会自动进入备份模式,并在备份完成后退出该模式。接受以下选项:

LABEL 'label'

设置备份的标签。如果未指定,将使用备份标签 base backup。标签的引用规则与 standard_conforming_strings 开启时的标准 SQL 字符串相同。

TARGET 'target'

告诉服务器将备份发送到哪里。如果目标是 client(默认值),则备份数据发送到客户端。如果目标是 server,则备份数据写入服务器,路径由 TARGET_DETAIL 选项指定。如果目标是 blackhole,则备份数据不发送到任何地方;它会被简单地丢弃。

server 目标需要超级用户权限或被授予 pg_write_server_files 角色。

TARGET_DETAIL 'detail'

提供有关备份目标的附加信息。

目前,此选项只能在备份目标是 server 时使用。它指定了备份应写入的服务器目录。

PROGRESS [ boolean ]

如果设置为 true,则请求生成进度报告所需的信息。这将返回每个表空间头部的近似大小,可用于计算流的完成进度。这是通过在传输开始前一次性枚举所有文件大小来计算的,因此可能会对性能产生负面影响。特别是,在传输第一个数据之前可能需要更长时间。由于数据库文件在备份过程中可能会发生变化,因此大小仅是近似值,并且可能在近似时间和实际文件传输之间增长和缩小。默认为 false。

CHECKPOINT { 'fast' | 'spread' }

设置基础备份开始时执行的检查点类型。默认为 spread

WAL [ boolean ]

如果设置为 true,则在备份中包含必要的 WAL 段。这将在基础目录 tar 文件中的 pg_wal 目录下包含开始和停止备份之间的所有文件。默认为 false。

WAIT [ boolean ]

如果设置为 true,备份将等待直到最后一个必需的 WAL 段被归档,或者在 WAL 归档未启用时发出警告。如果为 false,备份既不等待也不警告,由客户端负责确保必需的日志可用。默认为 true。

COMPRESSION 'method'

指示服务器使用指定的方法压缩备份。目前支持的方法是 gziplz4zstd

COMPRESSION_DETAIL detail

为所选的压缩方法指定详细信息。这只能与 COMPRESSION 选项结合使用。如果值为整数,则表示压缩级别。否则,它应该是逗号分隔的关键字列表,形式为 keywordkeyword=value。目前支持的关键字是 levellongworkers

level 关键字设置压缩级别。对于 gzip,压缩级别应为 1 到 9(默认 Z_DEFAULT_COMPRESSION-1)之间的整数;对于 lz4,压缩级别应为 1 到 12 之间的整数(默认 0 表示快速压缩模式);对于 zstd,压缩级别应为 ZSTD_minCLevel()(通常为 -131072)和 ZSTD_maxCLevel()(通常为 22)之间的整数(默认 ZSTD_CLEVEL_DEFAULT3)。

long 关键字启用长距离匹配模式,以提高压缩率,但会增加内存使用。长距离模式仅支持 zstd

workers 关键字设置应用于并行压缩的线程数。并行压缩仅支持 zstd

MAX_RATE rate

限制(节流)服务器到客户端每单位时间传输的最大数据量。预期的单位是千字节/秒。如果指定了此选项,则值必须为零,或者必须在 32 kB 到 1 GB(含)的范围内。如果传递零或未指定此选项,则不对传输施加任何限制。

TABLESPACE_MAP [ boolean ]

如果为 true,则在名为 tablespace_map 的文件中包含有关 pg_tblspc 目录中存在的符号链接的信息。表空间映射文件包括 pg_tblspc/ 目录中存在的每个符号链接名称以及该符号链接的完整路径。默认为 false。

VERIFY_CHECKSUMS [ boolean ]

如果为 true,则在启用了校验和的情况下进行基础备份时验证校验和。如果为 false,则跳过此操作。默认为 true。

MANIFEST manifest_option

当此选项的值为 yesforce-encode 时,将创建备份清单并随备份一起发送。清单是备份中存在的所有文件的列表,但不包括可能包含的任何 WAL 文件。它还存储每个文件的大小、最后修改时间,以及可选的校验和。值为 force-encode 会强制所有文件名进行十六进制编码;否则,仅对文件名是非 UTF8 字节序列的文件执行此类编码。force-encode 主要用于测试目的,以确保读取备份清单的客户端可以处理这种情况。为了兼容以前的版本,默认为 MANIFEST 'no'

MANIFEST_CHECKSUMS checksum_algorithm

指定应应用于备份清单中每个文件的校验和算法。目前可用的算法有 NONECRC32CSHA224SHA256SHA384SHA512。默认为 CRC32C

INCREMENTAL

请求增量备份。在使用此选项运行基础备份之前,必须先执行 UPLOAD_MANIFEST 命令。

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

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

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

spcoid (oid)

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

spclocation (text)

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

size (int8)

表空间的大约大小,以千字节(1024 字节)为单位,如果请求了进度报告;否则为 null。

在第二个常规结果集之后,将发送一个 CopyOutResponse。每个 CopyData 消息的有效负载将包含以下格式之一的消息:

new archive (B)
Byte1('n')

标识消息为新归档的开始。将有一个用于主数据目录的归档,以及一个用于每个附加表空间的归档;每个都将使用 tar 格式(遵循 POSIX 1003.1-2008 标准中指定的 ustar interchange format)。

String

此归档的文件名。

String

对于主数据目录,为空字符串。对于其他表空间,是创建此归档的目录的完整路径。

manifest (B)
Byte1('m')

标识消息为备份清单的开始。

archive or manifest data (B)
Byte1('d')

标识消息包含归档或清单数据。

Byten

Data bytes.

progress report (B)
Byte1('p')

标识消息为进度报告。

Int64

已处理的当前表空间的字节数。

在所有 CopyOutResponse 发送完毕后(或所有响应),将发送一个最终的普通结果集,包含备份的 WAL 结束位置,格式与起始位置相同。

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

  • postmaster.pid

  • postmaster.opts

  • pg_internal.init(在多个目录中找到)

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

  • 未记录的关系,除了用于在恢复时重新创建(空)未记录关系的 init fork。

  • pg_wal,包括子目录。如果备份运行时包含 WAL 文件,则会包含一个合成的 pg_wal 版本,但它将只包含备份正常工作所需的文件,而不是其其余内容。

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

  • 常规文件和目录以外的文件,例如符号链接(上面列出的目录除外)和特殊设备和操作系统文件,将被跳过。(pg_tblspc 中的符号链接会被保留。)

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

在上述所有命令中,当指定布尔类型 (boolean) 的参数时,可以省略 value 部分,这等同于指定 TRUE

提交更正

如果您在文档中看到任何不正确、与您对特定功能的体验不符或需要进一步澄清的内容,请使用 此表单 报告文档问题。