仅当旧逻辑复制集群的所有成员都为 17.0 或更高版本时,才支持迁移 逻辑复制集群。
pg_upgrade 会尝试迁移逻辑槽。 这有助于避免在新发布端手工定义相同的逻辑槽。 仅当旧集簇版本为 17.0 或更高时才支持逻辑槽迁移。 17.0 之前集簇中的逻辑槽会被静默忽略。
在开始升级发布端集簇前,请通过执行 ALTER SUBSCRIPTION ... DISABLE 临时禁用订阅。升级完成后再重新启用订阅。
pg_upgrade 升级逻辑槽有若干前置条件。 若不满足,将报错。
新集簇必须将 wal_level 设为 logical。
新集簇中 max_replication_slots 的配置值必须大于等于旧集簇中的槽数量。
旧集簇槽引用的输出插件必须安装在新 PostgreSQL 可执行文件目录中。
旧集簇必须已将所有事务和逻辑解码消息复制到订阅端。
旧集簇中的所有槽都必须可用,即不存在 pg_replication_slots.conflicting 不为 true 的槽。
新集簇中不能存在永久逻辑槽,即不能有 pg_replication_slots.temporary 为 false 的槽。
在新订阅端完成 订阅端配置。 pg_upgrade 会尝试迁移订阅依赖,包括 pg_subscription_rel 系统目录中的订阅表信息,以及订阅的复制源。 这样新订阅端上的逻辑复制可以从旧订阅端停止的位置继续。 仅当旧集簇版本为 17.0 或更高时才支持订阅依赖迁移。 17.0 之前集簇中的订阅依赖会被静默忽略。
pg_upgrade 升级订阅也有若干前置条件。 若不满足,将报错。
旧订阅端中所有订阅表应处于 i(initialize) 或 r(ready)状态。 可通过检查 pg_subscription_rel.srsubstate 验证。
旧集簇中每个订阅对应的复制源条目都必须存在。 可通过检查 pg_subscription 与 pg_replication_origin 系统表确认。
新集簇中的 max_active_replication_origins 配置值必须大于等于旧集簇中的订阅数量。
在升级订阅端时,发布端仍可执行写操作。这些变更会在订阅端升级完成后继续复制。
逻辑复制的限制同样适用于逻辑复制集群升级。详见 Section 29.8。
发布端升级的前置条件同样适用于逻辑复制集群升级。详见 Section 29.13.1。
订阅端升级的前置条件同样适用于逻辑复制集群升级。详见 Section 29.13.2。
升级逻辑复制集群需要在多个节点执行多个步骤。由于并非所有操作都是事务性的, 建议按 Section 25.3.2 所述先做好备份。
下列逻辑复制集群的升级步骤详见后文:
按照 Section 29.13.3.1 的步骤升级双节点逻辑复制集群。
按照 Section 29.13.3.2 的步骤升级级联逻辑复制集群。
按照 Section 29.13.3.3 的步骤升级双节点环形逻辑复制集群。
假设发布端位于 node1,订阅端位于 node2。 订阅端 node2 上有订阅 sub1_node1_node2,用于订阅来自 node1 的变更。
在 node2 上,使用 ALTER SUBSCRIPTION ... DISABLE 禁用所有订阅来自 node1 变更的订阅,例如:
/* node2 # */ ALTER SUBSCRIPTION sub1_node1_node2 DISABLE;
停止 node1 上的发布端服务器,例如:
pg_ctl -D /opt/PostgreSQL/data1 stop
使用目标新版本初始化 data1_upgraded 实例。
将发布端 node1 升级到目标新版本,例如:
pg_upgrade
--old-datadir "/opt/PostgreSQL/postgres/17/data1"
--new-datadir "/opt/PostgreSQL/postgres/18/data1_upgraded"
--old-bindir "/opt/PostgreSQL/postgres/17/bin"
--new-bindir "/opt/PostgreSQL/postgres/18/bin"
启动升级后的 node1 发布端服务器,例如:
pg_ctl -D /opt/PostgreSQL/data1_upgraded start -l logfile
停止 node2 上的订阅端服务器,例如:
pg_ctl -D /opt/PostgreSQL/data2 stop
使用目标新版本初始化 data2_upgraded 实例。
将订阅端 node2 升级到目标新版本,例如:
pg_upgrade
--old-datadir "/opt/PostgreSQL/postgres/17/data2"
--new-datadir "/opt/PostgreSQL/postgres/18/data2_upgraded"
--old-bindir "/opt/PostgreSQL/postgres/17/bin"
--new-bindir "/opt/PostgreSQL/postgres/18/bin"
启动升级后的 node2 订阅端服务器,例如:
pg_ctl -D /opt/PostgreSQL/data2_upgraded start -l logfile
在 node2 上,创建从 Step 1 到当前期间, 升级后的发布端 node1 新建的表,例如:
/* node2 # */ CREATE TABLE distributors (did integer PRIMARY KEY, name varchar(40));
在 node2 上,使用 ALTER SUBSCRIPTION ... ENABLE 启用所有订阅来自 node1 变更的订阅,例如:
/* node2 # */ ALTER SUBSCRIPTION sub1_node1_node2 ENABLE;
在 node2 上使用 ALTER SUBSCRIPTION ... REFRESH PUBLICATION 刷新订阅发布,例如:
/* node2 # */ ALTER SUBSCRIPTION sub1_node1_node2 REFRESH PUBLICATION;
上述步骤中先升级发布端,再升级订阅端。也可以采用类似步骤先升级订阅端, 再升级发布端。
假设有级联逻辑复制拓扑 node1->node2->node3。 其中 node2 订阅 node1 的变更, node3 订阅 node2 的变更。 node2 上有订阅 sub1_node1_node2, node3 上有订阅 sub1_node2_node3。
在 node2 上,使用 ALTER SUBSCRIPTION ... DISABLE 禁用所有订阅 node1 变更的订阅,例如:
/* node2 # */ ALTER SUBSCRIPTION sub1_node1_node2 DISABLE;
停止 node1 上的服务器,例如:
pg_ctl -D /opt/PostgreSQL/data1 stop
使用目标新版本初始化 data1_upgraded 实例。
将 node1 服务器升级到目标新版本,例如:
pg_upgrade
--old-datadir "/opt/PostgreSQL/postgres/17/data1"
--new-datadir "/opt/PostgreSQL/postgres/18/data1_upgraded"
--old-bindir "/opt/PostgreSQL/postgres/17/bin"
--new-bindir "/opt/PostgreSQL/postgres/18/bin"
启动升级后的 node1 服务器,例如:
pg_ctl -D /opt/PostgreSQL/data1_upgraded start -l logfile
在 node3 上,使用 ALTER SUBSCRIPTION ... DISABLE 禁用所有订阅 node2 变更的订阅,例如:
/* node3 # */ ALTER SUBSCRIPTION sub1_node2_node3 DISABLE;
停止 node2 上的服务器,例如:
pg_ctl -D /opt/PostgreSQL/data2 stop
使用目标新版本初始化 data2_upgraded 实例。
将 node2 服务器升级到目标新版本,例如:
pg_upgrade
--old-datadir "/opt/PostgreSQL/postgres/17/data2"
--new-datadir "/opt/PostgreSQL/postgres/18/data2_upgraded"
--old-bindir "/opt/PostgreSQL/postgres/17/bin"
--new-bindir "/opt/PostgreSQL/postgres/18/bin"
启动升级后的 node2 服务器,例如:
pg_ctl -D /opt/PostgreSQL/data2_upgraded start -l logfile
在 node2 上,创建从 Step 1 到当前期间, 升级后的发布端 node1 新建的表,例如:
/* node2 # */ CREATE TABLE distributors (did integer PRIMARY KEY, name varchar(40));
在 node2 上,使用 ALTER SUBSCRIPTION ... ENABLE 启用所有订阅 node1 变更的订阅,例如:
/* node2 # */ ALTER SUBSCRIPTION sub1_node1_node2 ENABLE;
在 node2 上使用 ALTER SUBSCRIPTION ... REFRESH PUBLICATION 刷新订阅发布,例如:
/* node2 # */ ALTER SUBSCRIPTION sub1_node1_node2 REFRESH PUBLICATION;
停止 node3 上的服务器,例如:
pg_ctl -D /opt/PostgreSQL/data3 stop
使用目标新版本初始化 data3_upgraded 实例。
将 node3 服务器升级到目标新版本,例如:
pg_upgrade
--old-datadir "/opt/PostgreSQL/postgres/17/data3"
--new-datadir "/opt/PostgreSQL/postgres/18/data3_upgraded"
--old-bindir "/opt/PostgreSQL/postgres/17/bin"
--new-bindir "/opt/PostgreSQL/postgres/18/bin"
启动升级后的 node3 服务器,例如:
pg_ctl -D /opt/PostgreSQL/data3_upgraded start -l logfile
在 node3 上,创建从 Step 6 到当前期间, 升级后的 node2 新建的表,例如:
/* node3 # */ CREATE TABLE distributors (did integer PRIMARY KEY, name varchar(40));
在 node3 上,使用 ALTER SUBSCRIPTION ... ENABLE 启用所有订阅 node2 变更的订阅,例如:
/* node3 # */ ALTER SUBSCRIPTION sub1_node2_node3 ENABLE;
在 node3 上使用 ALTER SUBSCRIPTION ... REFRESH PUBLICATION 刷新订阅发布,例如:
/* node3 # */ ALTER SUBSCRIPTION sub1_node2_node3 REFRESH PUBLICATION;
假设有环形逻辑复制拓扑 node1->node2 以及 node2->node1。 其中 node2 订阅 node1 的变更, node1 订阅 node2 的变更。 node1 上有订阅 sub1_node2_node1, node2 上有订阅 sub1_node1_node2。
在 node2 上,使用 ALTER SUBSCRIPTION ... DISABLE 禁用所有订阅 node1 变更的订阅,例如:
/* node2 # */ ALTER SUBSCRIPTION sub1_node1_node2 DISABLE;
停止 node1 上的服务器,例如:
pg_ctl -D /opt/PostgreSQL/data1 stop
使用目标新版本初始化 data1_upgraded 实例。
将 node1 服务器升级到目标新版本,例如:
pg_upgrade
--old-datadir "/opt/PostgreSQL/postgres/17/data1"
--new-datadir "/opt/PostgreSQL/postgres/18/data1_upgraded"
--old-bindir "/opt/PostgreSQL/postgres/17/bin"
--new-bindir "/opt/PostgreSQL/postgres/18/bin"
启动升级后的 node1 服务器,例如:
pg_ctl -D /opt/PostgreSQL/data1_upgraded start -l logfile
在 node2 上,使用 ALTER SUBSCRIPTION ... ENABLE 启用所有订阅 node1 变更的订阅,例如:
/* node2 # */ ALTER SUBSCRIPTION sub1_node1_node2 ENABLE;
在 node1 上,创建从 Step 1 到当前期间, node2 新建的表,例如:
/* node1 # */ CREATE TABLE distributors (did integer PRIMARY KEY, name varchar(40));
在 node1 上使用 ALTER SUBSCRIPTION ... REFRESH PUBLICATION 刷新订阅发布,从 node2 复制初始表数据,例如:
/* node1 # */ ALTER SUBSCRIPTION sub1_node2_node1 REFRESH PUBLICATION;
在 node1 上,使用 ALTER SUBSCRIPTION ... DISABLE 禁用所有订阅 node2 变更的订阅,例如:
/* node1 # */ ALTER SUBSCRIPTION sub1_node2_node1 DISABLE;
停止 node2 上的服务器,例如:
pg_ctl -D /opt/PostgreSQL/data2 stop
使用目标新版本初始化 data2_upgraded 实例。
将 node2 服务器升级到目标新版本,例如:
pg_upgrade
--old-datadir "/opt/PostgreSQL/postgres/17/data2"
--new-datadir "/opt/PostgreSQL/postgres/18/data2_upgraded"
--old-bindir "/opt/PostgreSQL/postgres/17/bin"
--new-bindir "/opt/PostgreSQL/postgres/18/bin"
启动升级后的 node2 服务器,例如:
pg_ctl -D /opt/PostgreSQL/data2_upgraded start -l logfile
在 node1 上,使用 ALTER SUBSCRIPTION ... ENABLE 启用所有订阅 node2 变更的订阅,例如:
/* node1 # */ ALTER SUBSCRIPTION sub1_node2_node1 ENABLE;
在 node2 上,创建从 Step 9 到当前期间, 升级后的 node1 新建的表,例如:
/* node2 # */ CREATE TABLE distributors (did integer PRIMARY KEY, name varchar(40));
在 node2 上使用 ALTER SUBSCRIPTION ... REFRESH PUBLICATION 刷新订阅发布,从 node1 复制初始表数据,例如:
/* node2 # */ ALTER SUBSCRIPTION sub1_node1_node2 REFRESH PUBLICATION;
如果您发现文档中有不正确的内容、与您使用特定功能的经验不符或需要进一步说明,请使用此表单来报告文档问题。