受支持版本: 当前版本 (18) / 15
开发版本: devel

29.13. 升级 #

仅当旧逻辑复制集群的所有成员都为 17.0 或更高版本时,才支持迁移 逻辑复制集群

29.13.1. 为发布端升级做准备 #

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.temporaryfalse 的槽。

29.13.2. 为订阅端升级做准备 #

在新订阅端完成 订阅端配置pg_upgrade 会尝试迁移订阅依赖,包括 pg_subscription_rel 系统目录中的订阅表信息,以及订阅的复制源。 这样新订阅端上的逻辑复制可以从旧订阅端停止的位置继续。 仅当旧集簇版本为 17.0 或更高时才支持订阅依赖迁移。 17.0 之前集簇中的订阅依赖会被静默忽略。

pg_upgrade 升级订阅也有若干前置条件。 若不满足,将报错。

  • 旧订阅端中所有订阅表应处于 i(initialize) 或 r(ready)状态。 可通过检查 pg_subscription_rel.srsubstate 验证。

  • 旧集簇中每个订阅对应的复制源条目都必须存在。 可通过检查 pg_subscriptionpg_replication_origin 系统表确认。

  • 新集簇中的 max_active_replication_origins 配置值必须大于等于旧集簇中的订阅数量。

29.13.3. 升级逻辑复制集群 #

在升级订阅端时,发布端仍可执行写操作。这些变更会在订阅端升级完成后继续复制。

Note

逻辑复制的限制同样适用于逻辑复制集群升级。详见 Section 29.8

发布端升级的前置条件同样适用于逻辑复制集群升级。详见 Section 29.13.1

订阅端升级的前置条件同样适用于逻辑复制集群升级。详见 Section 29.13.2

Warning

升级逻辑复制集群需要在多个节点执行多个步骤。由于并非所有操作都是事务性的, 建议按 Section 25.3.2 所述先做好备份。

下列逻辑复制集群的升级步骤详见后文:

29.13.3.1. 升级双节点逻辑复制集群的步骤 #

假设发布端位于 node1,订阅端位于 node2。 订阅端 node2 上有订阅 sub1_node1_node2,用于订阅来自 node1 的变更。

  1. node2 上,使用 ALTER SUBSCRIPTION ... DISABLE 禁用所有订阅来自 node1 变更的订阅,例如:

    /* node2 # */ ALTER SUBSCRIPTION sub1_node1_node2 DISABLE;
    
  2. 停止 node1 上的发布端服务器,例如:

    pg_ctl -D /opt/PostgreSQL/data1 stop
    
  3. 使用目标新版本初始化 data1_upgraded 实例。

  4. 将发布端 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"
    
  5. 启动升级后的 node1 发布端服务器,例如:

    pg_ctl -D /opt/PostgreSQL/data1_upgraded start -l logfile
    
  6. 停止 node2 上的订阅端服务器,例如:

    pg_ctl -D /opt/PostgreSQL/data2 stop
    
  7. 使用目标新版本初始化 data2_upgraded 实例。

  8. 将订阅端 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"
    
  9. 启动升级后的 node2 订阅端服务器,例如:

    pg_ctl -D /opt/PostgreSQL/data2_upgraded start -l logfile
    
  10. node2 上,创建从 Step 1 到当前期间, 升级后的发布端 node1 新建的表,例如:

    /* node2 # */ CREATE TABLE distributors (did integer PRIMARY KEY, name varchar(40));
    
  11. node2 上,使用 ALTER SUBSCRIPTION ... ENABLE 启用所有订阅来自 node1 变更的订阅,例如:

    /* node2 # */ ALTER SUBSCRIPTION sub1_node1_node2 ENABLE;
    
  12. node2 上使用 ALTER SUBSCRIPTION ... REFRESH PUBLICATION 刷新订阅发布,例如:

    /* node2 # */ ALTER SUBSCRIPTION sub1_node1_node2 REFRESH PUBLICATION;
    

Note

上述步骤中先升级发布端,再升级订阅端。也可以采用类似步骤先升级订阅端, 再升级发布端。

29.13.3.2. 升级级联逻辑复制集群的步骤 #

假设有级联逻辑复制拓扑 node1->node2->node3。 其中 node2 订阅 node1 的变更, node3 订阅 node2 的变更。 node2 上有订阅 sub1_node1_node2node3 上有订阅 sub1_node2_node3

  1. node2 上,使用 ALTER SUBSCRIPTION ... DISABLE 禁用所有订阅 node1 变更的订阅,例如:

    /* node2 # */ ALTER SUBSCRIPTION sub1_node1_node2 DISABLE;
    
  2. 停止 node1 上的服务器,例如:

    pg_ctl -D /opt/PostgreSQL/data1 stop
    
  3. 使用目标新版本初始化 data1_upgraded 实例。

  4. 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"
    
  5. 启动升级后的 node1 服务器,例如:

    pg_ctl -D /opt/PostgreSQL/data1_upgraded start -l logfile
    
  6. node3 上,使用 ALTER SUBSCRIPTION ... DISABLE 禁用所有订阅 node2 变更的订阅,例如:

    /* node3 # */ ALTER SUBSCRIPTION sub1_node2_node3 DISABLE;
    
  7. 停止 node2 上的服务器,例如:

    pg_ctl -D /opt/PostgreSQL/data2 stop
    
  8. 使用目标新版本初始化 data2_upgraded 实例。

  9. 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"
    
  10. 启动升级后的 node2 服务器,例如:

    pg_ctl -D /opt/PostgreSQL/data2_upgraded start -l logfile
    
  11. node2 上,创建从 Step 1 到当前期间, 升级后的发布端 node1 新建的表,例如:

    /* node2 # */ CREATE TABLE distributors (did integer PRIMARY KEY, name varchar(40));
    
  12. node2 上,使用 ALTER SUBSCRIPTION ... ENABLE 启用所有订阅 node1 变更的订阅,例如:

    /* node2 # */ ALTER SUBSCRIPTION sub1_node1_node2 ENABLE;
    
  13. node2 上使用 ALTER SUBSCRIPTION ... REFRESH PUBLICATION 刷新订阅发布,例如:

    /* node2 # */ ALTER SUBSCRIPTION sub1_node1_node2 REFRESH PUBLICATION;
    
  14. 停止 node3 上的服务器,例如:

    pg_ctl -D /opt/PostgreSQL/data3 stop
    
  15. 使用目标新版本初始化 data3_upgraded 实例。

  16. 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"
    
  17. 启动升级后的 node3 服务器,例如:

    pg_ctl -D /opt/PostgreSQL/data3_upgraded start -l logfile
    
  18. node3 上,创建从 Step 6 到当前期间, 升级后的 node2 新建的表,例如:

    /* node3 # */ CREATE TABLE distributors (did integer PRIMARY KEY, name varchar(40));
    
  19. node3 上,使用 ALTER SUBSCRIPTION ... ENABLE 启用所有订阅 node2 变更的订阅,例如:

    /* node3 # */ ALTER SUBSCRIPTION sub1_node2_node3 ENABLE;
    
  20. node3 上使用 ALTER SUBSCRIPTION ... REFRESH PUBLICATION 刷新订阅发布,例如:

    /* node3 # */ ALTER SUBSCRIPTION sub1_node2_node3 REFRESH PUBLICATION;
    

29.13.3.3. 升级双节点环形逻辑复制集群的步骤 #

假设有环形逻辑复制拓扑 node1->node2 以及 node2->node1。 其中 node2 订阅 node1 的变更, node1 订阅 node2 的变更。 node1 上有订阅 sub1_node2_node1node2 上有订阅 sub1_node1_node2

  1. node2 上,使用 ALTER SUBSCRIPTION ... DISABLE 禁用所有订阅 node1 变更的订阅,例如:

    /* node2 # */ ALTER SUBSCRIPTION sub1_node1_node2 DISABLE;
    
  2. 停止 node1 上的服务器,例如:

    pg_ctl -D /opt/PostgreSQL/data1 stop
    
  3. 使用目标新版本初始化 data1_upgraded 实例。

  4. 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"
    
  5. 启动升级后的 node1 服务器,例如:

    pg_ctl -D /opt/PostgreSQL/data1_upgraded start -l logfile
    
  6. node2 上,使用 ALTER SUBSCRIPTION ... ENABLE 启用所有订阅 node1 变更的订阅,例如:

    /* node2 # */ ALTER SUBSCRIPTION sub1_node1_node2 ENABLE;
    
  7. node1 上,创建从 Step 1 到当前期间, node2 新建的表,例如:

    /* node1 # */ CREATE TABLE distributors (did integer PRIMARY KEY, name varchar(40));
    
  8. node1 上使用 ALTER SUBSCRIPTION ... REFRESH PUBLICATION 刷新订阅发布,从 node2 复制初始表数据,例如:

    /* node1 # */ ALTER SUBSCRIPTION sub1_node2_node1 REFRESH PUBLICATION;
    
  9. node1 上,使用 ALTER SUBSCRIPTION ... DISABLE 禁用所有订阅 node2 变更的订阅,例如:

    /* node1 # */ ALTER SUBSCRIPTION sub1_node2_node1 DISABLE;
    
  10. 停止 node2 上的服务器,例如:

    pg_ctl -D /opt/PostgreSQL/data2 stop
    
  11. 使用目标新版本初始化 data2_upgraded 实例。

  12. 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"
    
  13. 启动升级后的 node2 服务器,例如:

    pg_ctl -D /opt/PostgreSQL/data2_upgraded start -l logfile
    
  14. node1 上,使用 ALTER SUBSCRIPTION ... ENABLE 启用所有订阅 node2 变更的订阅,例如:

    /* node1 # */ ALTER SUBSCRIPTION sub1_node2_node1 ENABLE;
    
  15. node2 上,创建从 Step 9 到当前期间, 升级后的 node1 新建的表,例如:

    /* node2 # */ CREATE TABLE distributors (did integer PRIMARY KEY, name varchar(40));
    
  16. node2 上使用 ALTER SUBSCRIPTION ... REFRESH PUBLICATION 刷新订阅发布,从 node1 复制初始表数据,例如:

    /* node2 # */ ALTER SUBSCRIPTION sub1_node1_node2 REFRESH PUBLICATION;
    

提交更正

如果您发现文档中有不正确的内容、与您使用特定功能的经验不符或需要进一步说明,请使用此表单来报告文档问题。