pg_createsubscriber
pg_createsubscriber — 将物理副本转换为新的逻辑副本
大纲
pg_createsubscriber [option...]
{ -d | --database }
dbname
{ -D | --pgdata }
datadir
{ -P | --publisher-server }
connstr
描述
pg_createsubscriber 从物理备库创建新的逻辑副本。指定数据库中的所有表都会包含在逻辑复制配置中。每个数据库都会创建一对发布和订阅对象。该工具必须在目标服务器上运行。
成功运行后,目标服务器的状态类似于一个全新的逻辑复制配置。逻辑复制配置与 pg_createsubscriber 之间的主要区别在于数据同步的完成方式。pg_createsubscriber 不会复制初始表数据。它只执行同步阶段,以确保每个表都达到同步状态。
pg_createsubscriber 主要面向大型数据库系统,因为在逻辑复制配置中,大部分时间都花在复制初始数据上。此外,在数据同步上花费较长时间的一个副作用通常是,会有大量在初始数据复制期间产生的更改需要应用,这会进一步延后逻辑副本可用的时间。对于较小的数据库,建议建立带初始数据同步的逻辑复制。详见 CREATE SUBSCRIPTION 的
copy_data 选项。
选项
pg_createsubscriber 接受以下命令行参数:
-a--all#在目标服务器上的每个数据库中创建一个订阅。模板数据库以及不允许连接的数据库除外。为发现所有数据库的列表,工具会使用
--publisher-server连接字符串中指定的数据库名连接到源服务器;如果未指定,则使用postgres数据库;如果该数据库不存在,则使用template1。指定此选项时,会使用自动生成的订阅、发布和复制槽名称。此选项不能与--database、--publication、--replication-slot或--subscription一起使用。-ddbname--database=#dbname要在其中创建订阅的数据库名称。通过多次指定
-d可以选择多个数据库。此选项不能与-a一起使用。如果未提供-d选项,数据库名将从-P选项中获取。如果在-d选项或-P选项中都未指定数据库名,且又未指定-a选项,则会报告错误。-Ddatadir--pgdata=#datadir包含物理副本中的集簇目录的目标目录。
-ldirectory--logdir=#directory指定日志目录的名称。如果该目录不存在,则会创建一个新目录。还会创建一个带时间戳的子目录,用于标识运行 pg_createsubscriber 的时间。该子目录中会创建以下两个日志文件。
pg_createsubscriber_server.log:记录与停止和启动备库相关的日志。pg_createsubscriber_internal.log:记录内部诊断输出(校验、检查等)。
默认情况下,umask 设为 077,因此日志文件只有运行该命令的用户可读。不过,如果目标数据目录配置为允许组读访问,pg_createsubscriber 会调整日志文件权限以匹配。这确保日志文件的安全性与数据库集簇本身保持一致。
-n--dry-run#执行除实际修改目标目录之外的所有步骤。
-pport--subscriber-port=#port目标服务器监听连接的端口号。默认为让目标服务器在 50432 端口上运行,以避免意外的客户端连接。
-Pconnstr--publisher-server=#connstr到发布者的连接字符串。详情见第 32.1.1 节。
-sdir--socketdir=#dir目标服务器上 postmaster 套接字所使用的目录。默认值为当前目录。
-tseconds--recovery-timeout=#seconds等待恢复结束的最大秒数。设为 0 表示禁用超时限制。默认值为 0。
-T--enable-two-phase#为订阅启用
two_phase两阶段提交。当指定多个数据库时,此选项会统一应用于在这些数据库上创建的所有订阅。默认值为false。-Uusername--subscriber-username=#username连接目标服务器所使用的用户名。默认是当前操作系统用户名。
-v--verbose#启用详细模式。这将使 pg_createsubscriber 向标准错误输出进度消息以及每个步骤的详细信息。重复指定该选项会让更多调试级消息出现在标准错误中。
--clean=#objtype从目标服务器上的指定数据库中删除指定类型的所有对象。
publications:为该订阅者建立的FOR ALL TABLES发布总是会被删除;指定此对象类型还会删除从源服务器复制过来的其他所有发布。
被选中要删除的对象都会逐个记录到日志中,包括在
--dry-run期间也是如此。没有机会干预或停止这些对象的删除,因此可以考虑使用 pg_dump 先对它们进行备份。--config-file=#filename为目标数据目录使用指定的主配置文件。pg_createsubscriber 在内部使用 pg_ctl 命令来启动和停止目标服务器。如果实际的
postgresql.conf配置文件存放在数据目录之外,此选项允许你显式指定它。--publication=#name用于建立逻辑复制的发布名称。通过多次指定
--publication可以指定多个发布。发布名称的数量必须与指定的数据库数量一致,否则会报告错误。多个发布名称开关的顺序必须与数据库开关的顺序一致。如果未指定此选项,则会为发布分配一个生成的名称。此选项不能与--all一起使用。如果指定的发布已经存在于发布者上,则会复用它。如果指定的发布包含一个表列表,那么这对部分复制数据库很有用。如果该发布不存在,则会自动以
FOR ALL TABLES创建它。使用--dry-run选项可以预览哪些发布会被复用、哪些会被创建。--replication-slot=#name用于建立逻辑复制的复制槽名称。通过多次指定
--replication-slot可以指定多个复制槽。复制槽名称的数量必须与指定的数据库数量一致,否则会报告错误。多个复制槽名称开关的顺序必须与数据库开关的顺序一致。如果未指定此选项,则使用订阅名称作为复制槽名称。此选项不能与--all一起使用。--subscription=#name用于建立逻辑复制的订阅名称。通过多次指定
--subscription可以指定多个订阅。订阅名称的数量必须与指定的数据库数量一致,否则会报告错误。多个订阅名称开关的顺序必须与数据库开关的顺序一致。如果未指定此选项,则会为订阅分配一个生成的名称。此选项不能与--all一起使用。-V--version#打印 pg_createsubscriber 版本并退出。
-?--help#显示 pg_createsubscriber 命令行参数的帮助并退出。
注解
前置条件
要让 pg_createsubscriber 将目标服务器转换为逻辑副本,需要满足一些前提条件。如果不满足这些条件,就会报告错误。源服务器和目标服务器的主版本必须与
pg_createsubscriber 相同。给定的目标数据目录必须与源数据目录具有相同的系统标识符。为目标数据目录指定的数据库用户必须具备创建订阅以及使用 pg_replication_origin_advance()
的权限。
目标服务器必须作为物理备库使用。目标服务器必须将 max_active_replication_origins 和 max_logical_replication_workers 配置为大于等于指定数据库数量的值。目标服务器必须将 max_worker_processes 配置为大于指定数据库数量的值。目标服务器必须接受本地连接。如果计划使用 --enable-two-phase
开关,还需要适当地设置 max_prepared_transactions。
源服务器必须接受来自目标服务器的连接。源服务器不能处于恢复中。源服务器必须将 wal_level 设置为 replica 或
logical。源服务器必须将 max_replication_slots 配置为大于等于指定数据库数量加现有复制槽数量的值。源服务器必须将 max_wal_senders 配置为大于等于指定数据库数量与现有 WAL 发送进程数量之和的值。
警告
若 pg_createsubscriber 在目标服务器被提升后失败,数据目录很可能已处于不可恢复状态。此时建议重新创建新的备库。
在转换过程中,pg_createsubscriber 通常会使用不同的连接设置来启动目标服务器。因此,对目标服务器的连接应该会失败。
由于逻辑复制不复制 DDL 命令,运行 pg_createsubscriber 期间应避免执行会更改数据库模式的 DDL 命令。若目标服务器已转换为逻辑副本,相关 DDL 可能不会被复制,从而引发错误。
若 pg_createsubscriber 处理过程中失败,会删除在源服务器上创建的对象(发布、复制槽)。如果目标服务器无法连接到源服务器,删除可能失败。在这种情况下,警告消息会提示遗留的对象。如果目标服务器正在运行,它会被停止。
若复制使用了 primary_slot_name,在逻辑复制配置完成后会从源服务器移除该复制槽。
如果目标服务器是同步副本,运行 pg_createsubscriber 期间,主库上的事务提交可能会在等待复制时阻塞。
除非指定 --enable-two-phase,pg_createsubscriber 会在禁用两阶段提交的情况下建立逻辑复制。这意味着任何预备事务都会在 COMMIT PREPARED 时被复制,而不会事先进行预备。配置完成后,你可以手动删除并重新创建订阅,并启用 two_phase
选项。
pg_createsubscriber 会使用 pg_resetwal 修改系统标识符。这样可以避免目标服务器可能使用源服务器的 WAL 文件。如果目标服务器还有备库,复制将会中断,应创建一个新的备库。
若缺少必需 WAL 文件,复制可能失败。为避免该问题,源服务器必须将 max_slot_wal_keep_size 设置为 -1,以确保必需 WAL 文件不会被提前移除。
工作原理
基本思路是从源服务器获得复制起点,并从该位置开始建立逻辑复制:
使用指定命令行选项启动目标服务器。若目标服务器已在运行,pg_createsubscriber 会报错终止。
检查目标服务器是否可以转换,同时也会对源服务器进行一些检查。若任一前置条件不满足,pg_createsubscriber 会报错终止。
在源服务器上为每个指定的数据库创建一个发布和一个复制槽。每个发布都以
FOR ALL TABLES创建。若未指定--publication,发布名称模式为“pg_createsubscriber_%u_%x”(参数:数据库oid、随机int)。若未指定--replication-slot,复制槽的名称模式如下:“pg_createsubscriber_%u_%x”(参数:数据库oid、随机int)。这些复制槽将在后续步骤中被订阅使用。最后一个复制槽的 LSN 会在 recovery_target_lsn 参数中用作停止点,也会被订阅用作复制起点。这样可以保证不会丢失任何事务。将恢复参数写入目标数据目录中的独立配置文件
pg_createsubscriber.conf,该文件通过目标数据目录中的postgresql.auto.conf里的include_if_exists引入,然后重启目标服务器。它指定了恢复将推进到的预写式日志位置的 LSN(recovery_target_lsn)。它还将promote指定为服务器在达到恢复目标后应执行的动作。还会添加其他恢复参数,以避免恢复过程中出现意外行为,例如一达到一致状态就结束恢复(WAL 应继续应用到复制起始位置),或者因指定多个恢复目标而失败。当服务器退出备库模式并接受读写事务时,该步骤结束。如果设置了--recovery-timeout选项,而恢复在给定秒数内没有结束,pg_createsubscriber 就会终止。完成后,被包含的配置文件会重命名为pg_createsubscriber.conf.disabled,使其不再在后续重启时加载。在目标服务器上为每个指定数据库创建订阅。若未指定
--subscription,名称模式为“pg_createsubscriber_%u_%x”(参数:数据库oid、随机int)。该订阅不会复制源服务器上的现有数据,也不会创建复制槽,而是使用前一步中创建的复制槽。订阅会被创建,但尚不启用,因为必须在启动复制之前先将复制进度设置到复制起点。删除在目标服务器上被复制过来的发布(这些发布是在复制起点前创建的),它们在订阅者上没有用途。
将每个订阅的复制进度设置为复制起点。当目标服务器开始恢复过程时,它会追赶到复制起点。这正是每个订阅要用作初始复制位置的 LSN。由于订阅已经创建,因此可以取得复制源名称。使用复制源名称和复制起点调用
pg_replication_origin_advance()以设置初始复制位置。在目标服务器上启用每个指定数据库的订阅。订阅将从复制起点开始应用事务。
若备库使用了 primary_slot_name,该复制槽之后不再有用,故将其删除。
若备库包含故障切换复制槽,它们后续无法继续同步,故将其删除。
更新目标服务器上的系统标识符。会运行 pg_resetwal 来修改系统标识符。由于
pg_resetwal的要求,目标服务器会被停止。
示例
要从位于 foo 的物理副本为数据库
hr 和 finance 创建逻辑副本:
$pg_createsubscriber -D /usr/local/pgsql/data -P "host=foo" -d hr -d finance