9.3 9.4 9.5 9.6 10 11 12 13 14 15 16 17 Current(18)
PostgreSQL中文社区 问题报告 纠错本页面

29.13. 升级 #

29.13.1. 为发布者升级做准备
29.13.2. 准备订阅者升级
29.13.3. 升级逻辑复制集群

迁移 逻辑复制集群 仅在旧逻辑复制 集群的所有成员版本为 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 能够升级订阅。如果这些条件未满足,将会报告错误。

29.13.3. 升级逻辑复制集群 #

在升级订阅者时,可以在发布者上执行写操作。这些更改将在 订阅者升级完成后复制到订阅者。

注意

逻辑复制的限制同样适用于逻辑复制集群的升级。有关详细信息,请参见 第 29.8 节

发布者升级的先决条件同样适用于逻辑复制集群的升级。有关详细信息,请参见 第 29.13.1 节

订阅者升级的先决条件同样适用于逻辑复制集群的升级。有关详细信息,请参见 第 29.13.2 节

警告

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

升级以下逻辑复制集群的步骤如下所述:

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

假设发布者在 node1,而订阅者在 node2。订阅者 node2 有一个订阅 sub1_node1_node2,它正在订阅来自 node1 的更改。

  1. 通过使用 ALTER SUBSCRIPTION ... DISABLE,禁用 所有在 node2 上订阅来自 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 上,创建在升级后的发布者 node1 服务器中创建的任何表, 例如:

    /* node2 # */ CREATE TABLE distributors (did integer PRIMARY KEY, name varchar(40));
    

  11. 启用所有在 node2 上订阅来自 node1 的更改的订阅, 使用 ALTER SUBSCRIPTION ... ENABLE, 例如:

    /* node2 # */ ALTER SUBSCRIPTION sub1_node1_node2 ENABLE;
    

  12. 使用 ALTER SUBSCRIPTION ... REFRESH PUBLICATION 刷新 node2 订阅的出版物,例如:

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

注意

在上述步骤中,首先升级发布者,然后是订阅者。或者,用户可以使用类似的步骤 首先升级订阅者,然后是发布者。

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

假设我们有一个级联的逻辑复制设置 node1->node2->node3。 这里 node2 正在订阅来自 node1 的更改,而 node3 正在订阅 来自 node2 的更改。 node2 有一个订阅 sub1_node1_node2,它正在 订阅来自 node1 的更改。 node3 有一个订阅 sub1_node2_node3,它正在订阅 来自 node2 的更改。

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

    /* 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 ... DISABLEnode2 订阅更改,例如:

    /* 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 上,创建在升级后的发布者 node1 服务器中创建的任何表,这些表是在 步骤 1 之间创建的,例如:

    /* node2 # */ CREATE TABLE distributors (did integer PRIMARY KEY, name varchar(40));
    

  12. 启用所有在 node2 上订阅来自 node1 的更改的订阅, 使用 ALTER SUBSCRIPTION ... ENABLE, 例如:

    /* node2 # */ ALTER SUBSCRIPTION sub1_node1_node2 ENABLE;
    

  13. 使用 ALTER SUBSCRIPTION ... REFRESH PUBLICATION 刷新 node2 订阅的出版物,例如:

    /* 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 上创建在升级后的 node2 中创建的任何表,时间范围是 步骤 6 到现在, 例如:

    /* node3 # */ CREATE TABLE distributors (did integer PRIMARY KEY, name varchar(40));
    

  19. 启用在 node3 上的所有订阅,这些订阅 来自 node2 的更改,使用 ALTER SUBSCRIPTION ... ENABLE, 例如:

    /* node3 # */ ALTER SUBSCRIPTION sub1_node2_node3 ENABLE;
    

  20. 使用 ALTER SUBSCRIPTION ... REFRESH PUBLICATION 刷新 node3 订阅的发布, 例如:

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

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

假设我们有一个循环逻辑复制设置 node1->node2node2->node1。这里 node2 订阅来自 node1 的更改,而 node1 订阅 来自 node2 的更改。node1 有一个订阅 sub1_node2_node1,它 订阅来自 node2 的更改。 node2 有一个订阅 sub1_node1_node2,它订阅来自 node1 的更改。

  1. 通过使用 ALTER SUBSCRIPTION ... DISABLE,禁用 所有在 node2 上订阅来自 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 上订阅来自 node1 的更改的订阅, 使用 ALTER SUBSCRIPTION ... ENABLE, 例如:

    /* node2 # */ ALTER SUBSCRIPTION sub1_node1_node2 ENABLE;
    

  7. node1 上创建在 node2 中创建的任何表,时间范围是 步骤 1 到现在,例如:

    /* node1 # */ CREATE TABLE distributors (did integer PRIMARY KEY, name varchar(40));
    

  8. 刷新 node1 订阅的发布,以 从 node2 复制初始表数据,使用 ALTER SUBSCRIPTION ... REFRESH PUBLICATION, 例如:

    /* node1 # */ ALTER SUBSCRIPTION sub1_node2_node1 REFRESH PUBLICATION;
    

  9. 禁用在 node1 上的所有订阅,这些订阅 来自 node2 的更改,使用 ALTER SUBSCRIPTION ... DISABLE, 例如:

    /* 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 上的所有订阅,这些订阅 来自 node2 的更改,使用 ALTER SUBSCRIPTION ... ENABLE, 例如:

    /* node1 # */ ALTER SUBSCRIPTION sub1_node2_node1 ENABLE;
    

  15. node2 上创建在升级后的 node1 中创建的任何表,时间范围是 步骤 9 到现在,例如:

    /* node2 # */ CREATE TABLE distributors (did integer PRIMARY KEY, name varchar(40));
    

  16. 刷新 node2 订阅的发布,以从 node1 复制初始表数据, 使用 ALTER SUBSCRIPTION ... REFRESH PUBLICATION, 例如:

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