↑↓ 选择↵ 打开⌫ 切换范围完整搜索

PG.CENTER 连接 PostgreSQL 文档、百科与生态知识。由 Pigsty 维护。

支持中的版本: 当前版本 (18)
开发中的版本: 19 / 20devel
开发快照。 PostgreSQL 20devel 尚未正式发布,内容仍可能变化。

29.14. 升级 #

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

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

pg_upgrade 会尝试迁移逻辑槽。这有助于避免在新发布端手工定义相同的逻辑槽。仅当旧集簇版本为 17.0 或更高时才支持逻辑槽迁移。17.0 之前集簇中的逻辑槽会被静默忽略。

在开始升级发布端集簇前,请通过执行 ALTER SUBSCRIPTION ... DISABLE 临时禁用订阅。升级完成后再重新启用订阅。

pg_upgrade 升级逻辑槽有若干前置条件。若不满足,将报错。

  • 新集簇必须将 wal_level 设为 replica 或 logical。

  • 新集簇中 max_replication_slots 的配置值必须大于等于旧集簇中的槽数量。

  • 旧集簇中复制槽引用的输出插件必须安装在新 PostgreSQL 可执行文件目录中。还必须将它们包含在新集簇的 output_plugin_libraries 中;有关安全信息,请参阅该参数的文档。

  • 旧集簇必须已将所有事务和逻辑解码消息复制到订阅端。

  • 旧集簇中的所有槽都必须可用,即它们的 pg_replication_slots.conflicting 都为 false。

  • 新集簇中不能存在任何永久逻辑槽,即所有已有逻辑槽的 pg_replication_slots.temporary 都必须设为 true。

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

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

注意

升级期间不会保留提交时间戳和复制源数据。因此,即使启用了 retain_dead_tuples,升级后的订阅端在应用升级前发布端产生的变更时,也可能无法检测冲突或记录相关的提交时间戳和复制源。另外,升级之后,清理可能立即移除冲突检测所需的已删除行。这会影响那些在升级前尚未复制的变更。为确保冲突跟踪一致,用户应确保所有可能冲突的变更都在启动升级前复制到订阅端。

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

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

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

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

  • 如果存在启用了 retain_dead_tuples 的订阅,新集簇中不能存在保留的复制槽“pg_conflict_detection”。此外,新集簇上的 wal_level 必须设置为 replica 或 logical。

29.14.3. 升级逻辑复制集群 #

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

注意

逻辑复制的限制同样适用于逻辑复制集群升级。详见第 29.9 节。

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

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

警告

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

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

29.14.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 上,创建从步骤 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;
    

注意

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

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

假设有级联逻辑复制拓扑 node1->node2->node3。其中 node2 订阅 node1 的变更,node3 订阅 node2 的变更。node2 上有订阅 sub1_node1_node2,node3 上有订阅 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 上,创建从步骤 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 上,创建从步骤 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.14.3.3. 升级双节点环形逻辑复制集群的步骤 #

假设有环形逻辑复制拓扑 node1->node2 以及 node2->node1。其中 node2 订阅 node1 的变更,node1 订阅 node2 的变更。node1 上有订阅 sub1_node2_node1,node2 上有订阅 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 上,创建从步骤 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 上,创建从步骤 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;
    

报告文档问题

阅读 上游文档. 反馈更正前请先核对 当前版本手册.