只能在旧的逻辑复制集群的所有成员都为 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(初始化)或 r(就绪)状态。这可以通过检查 pg_subscription_rel.srsubstate 来验证。
旧集群中应存在对应于每个订阅的复制源条目。这可以通过检查 pg_subscription 和 pg_replication_origin 系统表来找到。
新集群的 max_active_replication_origins 配置值必须大于或等于旧集群中存在的订阅数。
升级订阅服务器时,可以在发布服务器中执行写入操作。这些更改将在订阅服务器升级完成后复制到订阅服务器。
逻辑复制限制也适用于逻辑复制集群升级。有关详细信息,请参阅 第 29.8 节。
发布服务器升级的先决条件也适用于逻辑复制集群升级。有关详细信息,请参阅 第 29.13.1 节。
订阅服务器升级的先决条件也适用于逻辑复制集群升级。有关详细信息,请参阅 第 29.13.2 节。
升级逻辑复制集群需要在多个节点上执行多个步骤。由于并非所有操作都是事务性的,建议用户按照 第 25.3.2 节 中的说明进行备份。
下面将详细介绍升级以下逻辑复制集群的步骤
请按照 第 29.13.3.1 节 中指定的步骤来升级双节点逻辑复制集群。
请按照 第 29.13.3.2 节 中指定的步骤来升级级联逻辑复制集群。
请按照 第 29.13.3.3 节 中指定的步骤来升级双节点循环逻辑复制集群。
假设发布服务器在 node1,订阅服务器在 node2。订阅服务器 node2 有一个订阅 sub1_node1_node2,它订阅了来自 node1 的更改。
通过使用 ALTER SUBSCRIPTION ... DISABLE 命令,禁用 node2 上所有订阅了来自 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 上,创建在 步骤 1 和现在之间在升级后的发布服务器 node1 中创建的任何表,例如:
/* node2 # */ CREATE TABLE distributors (did integer PRIMARY KEY, name varchar(40));
通过使用 ALTER SUBSCRIPTION ... ENABLE 命令,启用 node2 上所有订阅了来自 node1 的更改的订阅,例如:
/* node2 # */ ALTER SUBSCRIPTION sub1_node1_node2 ENABLE;
使用 ALTER SUBSCRIPTION ... REFRESH PUBLICATION 命令刷新 node2 订阅的发布,例如:
/* node2 # */ ALTER SUBSCRIPTION sub1_node1_node2 REFRESH PUBLICATION;
在上述步骤中,先升级发布服务器,然后升级订阅服务器。或者,用户也可以使用类似的步骤先升级订阅服务器,然后升级发布服务器。
假设我们有一个级联逻辑复制设置 node1->node2->node3。这里 node2 订阅来自 node1 的更改,而 node3 订阅来自 node2 的更改。node2 有一个订阅 sub1_node1_node2,它订阅来自 node1 的更改。node3 有一个订阅 sub1_node2_node3,它订阅来自 node2 的更改。
通过使用 ALTER SUBSCRIPTION ... DISABLE 命令,禁用 node2 上所有订阅了来自 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
通过使用 ALTER SUBSCRIPTION ... DISABLE 命令,禁用 node3 上所有订阅了来自 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 上,创建在 步骤 1 和现在之间在升级后的发布服务器 node1 中创建的任何表,例如:
/* node2 # */ CREATE TABLE distributors (did integer PRIMARY KEY, name varchar(40));
通过使用 ALTER SUBSCRIPTION ... ENABLE 命令,启用 node2 上所有订阅了来自 node1 的更改的订阅,例如:
/* node2 # */ ALTER SUBSCRIPTION sub1_node1_node2 ENABLE;
使用 ALTER SUBSCRIPTION ... REFRESH PUBLICATION 命令刷新 node2 订阅的发布,例如:
/* 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 上,创建在 步骤 6 和现在之间在升级后的 node2 中创建的任何表,例如:
/* node3 # */ CREATE TABLE distributors (did integer PRIMARY KEY, name varchar(40));
通过使用 ALTER SUBSCRIPTION ... ENABLE 命令,启用 node3 上所有订阅了来自 node2 的更改的订阅,例如:
/* node3 # */ ALTER SUBSCRIPTION sub1_node2_node3 ENABLE;
使用 ALTER SUBSCRIPTION ... REFRESH PUBLICATION 命令刷新 node3 订阅的发布,例如:
/* node3 # */ ALTER SUBSCRIPTION sub1_node2_node3 REFRESH PUBLICATION;
假设我们有一个循环逻辑复制设置 node1->node2 和 node2->node1。这里 node2 订阅来自 node1 的更改,而 node1 订阅来自 node2 的更改。node1 有一个订阅 sub1_node2_node1,它订阅来自 node2 的更改。node2 有一个订阅 sub1_node1_node2,它订阅来自 node1 的更改。
通过使用 ALTER SUBSCRIPTION ... DISABLE 命令,禁用 node2 上所有订阅了来自 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
通过使用 ALTER SUBSCRIPTION ... ENABLE 命令,启用 node2 上所有订阅了来自 node1 的更改的订阅,例如:
/* node2 # */ ALTER SUBSCRIPTION sub1_node1_node2 ENABLE;
在 node1 上,创建在 步骤 1 和现在之间在 node2 中创建的任何表,例如:
/* node1 # */ CREATE TABLE distributors (did integer PRIMARY KEY, name varchar(40));
使用 ALTER SUBSCRIPTION ... REFRESH PUBLICATION 命令刷新 node1 订阅的发布,以从 node2 复制初始表数据,例如:
/* node1 # */ ALTER SUBSCRIPTION sub1_node2_node1 REFRESH PUBLICATION;
通过使用 ALTER SUBSCRIPTION ... DISABLE 命令,禁用 node1 上所有订阅了来自 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
通过使用 ALTER SUBSCRIPTION ... ENABLE 命令,启用 node1 上所有订阅了来自 node2 的更改的订阅,例如:
/* node1 # */ ALTER SUBSCRIPTION sub1_node2_node1 ENABLE;
在 node2 上,创建在 步骤 9 和现在之间在升级后的 node1 中创建的任何表,例如:
/* node2 # */ CREATE TABLE distributors (did integer PRIMARY KEY, name varchar(40));
使用 ALTER SUBSCRIPTION ... REFRESH PUBLICATION 命令刷新 node2 订阅的发布,以从 node1 复制初始表数据,例如:
/* node2 # */ ALTER SUBSCRIPTION sub1_node1_node2 REFRESH PUBLICATION;