Redrock Postgres 搜索 英文
版本: 9.3 / 9.4 / 9.5 / 9.6 / 10 / 11 / 12 / 13 / 14 / 15 / 16 / 17

pg_upgrade

pg_upgrade — 升级 PostgreSQL 服务器实例

语法

pg_upgrade -b oldbindir [-B newbindir] -d oldconfigdir -D newconfigdir [option...]

说明

pg_upgrade(以前称为 pg_migrator)允许存储在 PostgreSQL 数据文件中的数据升级到更高版本的 PostgreSQL 主要版本,而无需主要版本升级通常所需的数据转储/恢复,例如,从 12.14 到 13.10 或从 14.9 到 15.5。对于小版本升级,此操作不是必需的,例如,从 12.7 升级到 12.8 或从 14.1 升级到 14.5。

PostgreSQL 的主要版本会定期添加新功能,通常会更改系统表的布局,但内部数据存储格式很少更改。pg_upgrade 利用这一事实,通过创建新的系统表并简单地重新使用旧的用户数据文件来执行快速升级。如果未来的主要版本以使旧数据格式无法读取的方式更改了数据存储格式,则 pg_upgrade 将无法用于此类升级。(社区将尝试避免这种情况。)

pg_upgrade 会尽力确保旧集群和新集群是二进制兼容的,例如,通过检查兼容的编译时设置,包括 32/64 位二进制文件。任何外部模块也应该是二进制兼容的,这一点很重要,但 pg_upgrade 无法检查这一点。

pg_upgrade 支持从 9.2.X 及更高版本升级到当前 PostgreSQL 的主流版本,包括快照版和测试版。

选项

pg_upgrade 接受以下命令行参数

-b bindir
--old-bindir=bindir

旧的 PostgreSQL 可执行文件目录;环境变量 PGBINOLD

-B bindir
--new-bindir=bindir

新的 PostgreSQL 可执行文件目录;默认是 pg_upgrade 所在的目录;环境变量 PGBINNEW

-c
--check

仅检查群集,不要更改任何数据

-d configdir
--old-datadir=configdir

旧的数据库群集配置目录;环境变量 PGDATAOLD

-D configdir
--new-datadir=configdir

新的数据库群集配置目录;环境变量 PGDATANEW

-j njobs
--jobs=njobs

要使用的同时进程或线程数

-k
--link

使用硬链接,而不是将文件复制到新集群

-N
--no-sync

默认情况下,pg_upgrade 将等待升级集群中的所有文件都安全写入磁盘。此选项会导致 pg_upgrade 在不等待的情况下返回,速度更快,但意味着后续的操作系统崩溃可能会导致数据目录损坏。通常,此选项对于测试来说很有用,但不要在生产安装中使用。

-o 选项
--old-options 选项

选项将被直接传递至旧 postgres 命令;多次选项调用将被追加

-O 选项
--new-options 选项

选项将被直接传递至新 postgres 命令;多次选项调用将被追加

-p 端口
--old-port=端口

旧集群的端口号;环境变量 PGPORTOLD

-P 端口
--new-port=端口

新集群的端口号;环境变量 PGPORTNEW

-r
--retain

即使在成功完成之后,也保留 SQL 和日志文件

-s 目录
--socketdir=目录

升级期间用于命令服务器套接字的目录;默认目录是当前工作目录;环境变量 PGSOCKETDIR

-U 用户名
--username=用户名

集群的安装用户名;环境变量 PGUSER

-v
--verbose

启用详细的内部日志记录

-V
--version

显示版本信息,然后退出

--clone

使用高效的文件克隆(在某些系统上也称作 reflinks),而不是将文件复制到新集群中。这可以让数据文件几乎立即复制完成,既可以获得 -k/--link 的速度优势,同时又不对旧集群做出任何改动。

文件克隆仅在某些操作系统和文件系统上受支持。如果选择此选项但不受支持,pg_upgrade 运行将出错。目前,它在内核为 4.5 或更高版本且采用 Btrfs 和 XFS(在具有 reflink 支持的文件系统上创建的文件系统)的 Linux 上受支持,并在采用 APFS 的 macOS 上受支持。

--copy

将文件复制到新集群。这是默认设置。(另请参阅 --link--clone。)

--copy-file-range

使用 copy_file_range 系统调用以高效进行复制。在某些文件系统上,这会得到类似于 --clone 的结果,共享物理磁盘块;而在其他文件系统上,其可能仍然复制块,但这样做是通过优化路径。目前,它受支持的系统有 Linux 和 FreeBSD。

--sync-method=method

如果设置为 fsync(这是默认设置),pg_upgrade 将递归式打开并同步已升级集群数据目录中的所有文件。对文件的搜索会跟随符号链接查看 WAL 目录和每个已配置表空间。

在 Linux 上,可以使用 syncfs 来要求操作系统同步包含已升级集群数据目录、其 WAL 文件和每个表空间的整个文件系统。有关使用 syncfs 时需注意的注意事项的信息,请参见 recovery_init_sync_method

如果使用 --no-sync,则此选项无效。

-?
--help

显示帮助,然后退出

用法

以下是可以使用 pg_upgrade 执行升级的步骤

  1. 可选:移动旧集群

    如果你使用的是特定于版本的安装目录,例如 /opt/PostgreSQL/17,则无需移动旧集群。图形安装程序全部使用特定于版本的安装目录。

    如果你的安装目录不是特定于版本的,例如 /usr/local/pgsql,则有必要移动当前 PostgreSQL 安装目录,以便它不会干扰新的 PostgreSQL 安装。一旦当前 PostgreSQL 服务器关闭,就可以对 PostgreSQL 安装目录重命名;假设旧目录是 /usr/local/pgsql,则你可以执行

    mv /usr/local/pgsql /usr/local/pgsql.old
    

    来重命名目录。

  2. 对于源安装,构建新版本

    使用与旧集群兼容的 configure 标记来构建新的 PostgreSQL 代码。在开始升级之前,pg_upgrade 将检查 pg_controldata 以确保所有设置兼容。

  3. 安装新的 PostgreSQL 二进制文件

    安装新服务器的二进制文件和支持文件。默认安装已包括 pg_upgrade

    对于源代码形式的安装,如果你希望在新服务器上自定义安装位置,则需要使用 prefix 变量

    make prefix=/usr/local/pgsql.new install
    
  4. 初始化新的 PostgreSQL 集群

    使用 initdb 初始化新的集群。再次提醒,请使用与旧集群匹配的兼容 initdb 标志。许多预构建的安装程序都会自动执行此步骤。对于新集群,无需启动。

  5. 安装扩展共享对象文件

    许多扩展和自定义模块,无论来自 contrib 还是其他来源,都使用共享对象文件(或 DLL),例如 pgcrypto.so。如果旧集群使用了这些文件,则新服务器二进制文件匹配的共享对象文件必须安装到新集群中,通常是通过操作系统命令安装的。不要加载模式定义,例如 CREATE EXTENSION pgcrypto,因为这些定义会从旧集群中复制过来。如果可以更新扩展,则 pg_upgrade 将报告此信息并创建一个脚本,可以稍后运行该脚本来更新扩展。

  6. 复制自定义全文搜索文件

    将任何自定义全文搜索文件(词典、同义词、同义词库、停用词)从旧集群复制到新集群中。

  7. 调整身份验证

    pg_upgrade 将多次连接到旧服务器和新服务器,因此可能需要在 pg_hba.conf 中将身份验证设置为 peer,或使用 ~/.pgpass 文件(请参阅 第 32.16 节)。

  8. 为发布服务器升级做好准备

    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

  9. 为订阅者升级做准备

    在新订阅者中设置 订阅者配置pg_upgrade 会尝试迁移订阅依赖项,其中包括 pg_subscription_rel 系统目录中存在的订阅表信息以及订阅的复制源。这会让新订阅者的逻辑复制继续从旧订阅者停留的位置。仅当旧集群的版本为 17.0 或更高版本时才支持订阅依赖项的迁移。版本 17.0 之前的集群中的订阅依赖项将被静默忽略。

    pg_upgrade 可以升级订阅有一些先决条件。如果不满足这些条件,将报告错误。

    • 旧订阅者中的所有订阅表都应处于 i(初始化)或 r(准备就绪)状态。可以通过检查 pg_subscription_rel.srsubstate 来验证这一点。

    • 对应于每个订阅的复制源条目应存在于旧集群中。可以通过检查 pg_subscriptionpg_replication_origin 系统表来找到它。

    • 新集群的 max_replication_slots 必须配置为大于或等于旧集群中存在的订阅数量。

  10. 停止这两台服务器

    确保在 Unix 上使用以下命令停止两台数据库服务器,例如

    pg_ctl -D /opt/PostgreSQL/12 stop
    pg_ctl -D /opt/PostgreSQL/17 stop
    

    或在 Windows 上使用适当的服务名称

    NET STOP postgresql-12
    NET STOP postgresql-17
    

    在此关闭期间,流复制和日志传送备用服务器必须正在运行,以便他们可以接收所有更改。

  11. 为备用服务器升级做准备

    如果您按照第 13 步 中概述的方法升级备用服务器,可通过对旧主服务器和备用集群运行 pg_controldata 来验证旧备用服务器是否已赶上。验证所有集群中 最近的检查点位置 值是否一致。此外,请确保新主集群的 postgresql.conf 文件中的 wal_level 未设置为 minimal

  12. 运行 pg_upgrade

    始终运行新服务器的 pg_upgrade 二进制文件,而不是旧服务器的。 pg_upgrade 需要指定旧集群和新集群的数据和可执行(bin)目录。您还可以指定用户和端口值,以及是链接数据文件还是使用默认的复制行为克隆数据文件。

    如果您使用链接模式,升级将快得多(无文件复制)且占用更少的磁盘空间,但升级后一旦启动新集群,您将无法访问旧集群。链接模式还要求旧集群和新集群的数据目录位于相同的文件系统中。(表空间和 pg_wal 可以位于不同的文件系统中。)克隆模式同样具备提速和节省磁盘空间的优点,但不会在新集群启动后导致旧集群不可用。克隆模式还要求旧数据和新数据目录位于相同的文件系统中。该模式仅在某些操作系统和文件系统上可用。

    --jobs 选项允许使用多个 CPU 内核并行复制/链接文件以及转储和恢复数据库架构;可以从 CPU 内核和表空间数量的最大值开始。该选项可以极大地减少在多处理器机器上运行的多数据库服务器的升级时间。

    对于 Windows 用户,您必须登录到管理帐户,然后在双引号包围的目录中运行 pg_upgrade,例如

    pg_upgrade.exe
            --old-datadir "C:/Program Files/PostgreSQL/12/data"
            --new-datadir "C:/Program Files/PostgreSQL/17/data"
            --old-bindir "C:/Program Files/PostgreSQL/12/bin"
            --new-bindir "C:/Program Files/PostgreSQL/17/bin"
    

    一旦启动,pg_upgrade 将验证两个集群兼容,然后进行升级。您可以使用 pg_upgrade --check 仅执行检查,即使旧服务器仍在运行。 pg_upgrade --check 还将概述升级后您需要进行的任何手动调整。如果您打算使用链接或克隆模式,则应使用选项 --link--clone--check 一起启用特定于模式的检查。 pg_upgrade 需要当前目录的写入权限。

    显然,升级期间任何人都不得访问集群。pg_upgrade 默认在端口 50432 上运行服务器,以避免意外客户端连接。执行升级时,您可以对两个集群使用相同的端口号,因为旧集群和新集群不会同时运行。但是,在检查一个运行中的旧服务器时,旧端口号和新端口号必须不同。

    如果在恢复数据库架构时发生错误,pg_upgrade 将退出,您将必须按照以下 步骤 19 中所述,恢复到旧集群。要重新尝试 pg_upgrade,您需要修改旧集群,以便成功恢复 pg_upgrade 架构。如果问题出在 contrib 模块,您可能需要从旧集群卸载 contrib 模块,并在升级后将它安装到新集群中,前提是该模块没有用于储存用户数据。

  13. 升级流复制和日志传输待机服务器

    如果您使用了链接模式并且有流复制(请参见 章节 26.2.5)或日志传输(请参见 章节 26.2)待机服务器,则可以按照以下步骤快速升级。您不必在待机服务器上运行 pg_upgrade,而应该在主服务器上运行 rsync。请勿启动任何服务器。

    如果您 没有 使用链接模式,没有使用或不希望使用 rsync,或者希望一个更简单的解决方案,则跳过本节中的说明,并在 pg_upgrade 完成并且新的主服务器正在运行后,简单地重新创建待机服务器。

    1. 在待机服务器上安装新的 PostgreSQL 二进制文件

      确保已在新旧所有待机服务器上安装了新的二进制文件和支持文件。

    2. 确保不存在新的待机数据目录

      确保不存在或清空新的待机数据目录。如果已运行 initdb,请删除待机服务器的新数据目录。

    3. 安装扩展共享对象文件

      在您在新主集群中安装的相同扩展共享对象文件中安装新的待机文件。

    4. 停止待机服务器

      如果待机服务器仍在运行,请立即使用上述说明对其进行停止。

    5. 保存配置文件

      保存旧待机配置文件目录中您需要保留的任何配置文件,例如 postgresql.conf(以及它包含的任何文件)、postgresql.auto.confpg_hba.conf,因为它们将在下一步中被覆盖或删除。

    6. 运行 rsync

      使用链接模式时,可以使用 rsync 对备用服务器进行快速升级。为此,在主服务器上一个高于旧和新数据库群集目录的目录中,为每个备用服务器在 服务器上运行以下命令

      rsync --archive --delete --hard-links --size-only --no-inc-recursive old_cluster new_cluster remote_dir
      

      其中 old_clusternew_cluster 相对于主服务器上的当前目录,而 remote_dir高于 备用服务器上新旧群集目录的位置。指定目录下主服务器和备用服务器的目录结构必须匹配。请参阅 rsync 手册页,了解指定远程目录的详细信息,例如

      rsync --archive --delete --hard-links --size-only --no-inc-recursive /opt/PostgreSQL/12 \
            /opt/PostgreSQL/17 standby.example.com:/opt/PostgreSQL
      

      您可以使用 rsync--dry-run 选项验证命令将执行的操作。虽然 rsync 必须至少在一个备用服务器上运行,但只要未启动升级的备用服务器,就可以在已升级的备用服务器上运行 rsync 来升级其他备用服务器。

      此操作是记录由 pg_upgrade 链接模式创建的链接,该链接连接主服务器上旧和新群集中的文件。然后,它会找到备用服务器旧群集中的匹配文件,并在备用服务器的新群集创建链接。未在主服务器上链接的文件将从主服务器复制到备用服务器。(它们通常很小。)这提供了快速的备用服务器升级。遗憾的是,rsync 会无故复制与临时表和未记录表关联的文件,因为这些文件通常不存在于备用服务器上。

      如果您有表空间,您需要为每个表空间目录运行一个类似的 rsync 命令,例如

      rsync --archive --delete --hard-links --size-only --no-inc-recursive /vol1/pg_tblsp/PG_12_201909212 \
            /vol1/pg_tblsp/PG_17_202307071 standby.example.com:/vol1/pg_tblsp
      

      如果已将 pg_wal 重新分配到数据目录之外,也必须在这些目录上运行 rsync

    7. 配置流复制和日志传输备用服务器

      为日志传输配置服务器。(您不需要运行 pg_backup_start()pg_backup_stop() 或进行文件系统备份,因为备用服务器仍与主服务器同步。)如果旧主服务器版本低于 17.0,则不会将主服务器上的任何槽复制到新备用服务器,所以必须手动重新创建旧备用服务器上的所有槽。如果旧主服务器是 17.0 或更高版本,则只会将主服务器上的逻辑槽复制到新备用服务器,但不会复制旧备用服务器上的其他槽,因此必须手动重新创建。

  14. 还原 pg_hba.conf

    如果您修改了 pg_hba.conf,请恢复其原始的设置。还需要调整新集群中的其他配置文件来匹配旧集群,例如,postgresql.conf(以及它所包含的任何文件),postgresql.auto.conf

  15. 启动新服务器

    现在可以安全地启动新服务器,然后启动任何 rsync 备用服务器。

  16. 升级后处理

    如果需要任何升级后处理,pg_upgrade 在完成时会发出警告。它还将生成管理员必须运行的脚本文件。脚本文件将连接到需要升级后处理的每个数据库。应当使用以下命令运行每个脚本

    psql --username=postgres --file=script.sql postgres
    

    这些脚本可以按任意顺序运行,并且在运行后可以将其删除。

    警告

    通常,在重建脚本运行完成之前访问重建脚本中引用的表是不安全的;这样做可能会导致不正确的结果或较差的性能。未在重建脚本中引用的表可以立即访问。

  17. 统计信息

    由于 pg_upgrade 不会传输优化器统计信息,因此您将在升级结束时被指示去运行一个命令来重新生成这些信息。您可能需要设置连接参数,以匹配您的新集群。

    使用 vacuumdb --all --analyze-only 可以有效生成此类统计信息,使用 --jobs 可以加速生成。选项 --analyze-in-stages 可以用于快速生成最少的统计信息。如果 vacuum_cost_delay 设置为非零值,则可以使用 PGOPTIONS 覆盖此设置,以加快统计信息生成速度,例如,PGOPTIONS='-c vacuum_cost_delay=0' vacuumdb ...

  18. 删除旧集群

    一旦您对升级感到满意,则可以通过运行 pg_upgrade 完成时所提到的脚本来删除旧集群的数据目录。(如果旧数据目录中存在用户定义的表空间,则无法自动删除。)您还可以删除旧的安装目录(例如,binshare)。

  19. 恢复旧集群

    如果您在运行 pg_upgrade 后希望恢复旧集群,则有几种选择

    • 如果使用了 --check 选项,则旧集群未经修改;它可以重新启动。

    • 如果 使用 --link 选项,则旧集群未经修改;它可以重新启动。

    • 如果使用了 --link 选项,数据文件可能会在旧集群和新集群之间共享

      • 如果 pg_upgrade 在链接开始之前中止,则旧集群保持不变;可以重新启动它。

      • 如果您没有启动新集群,则旧集群保持不变,但当开始链接时,将一个 .old 后缀追加到 $PGDATA/global/pg_control 中。要重新使用旧集群,请从 $PGDATA/global/pg_control 中删除 .old 后缀;然后,您可以重新启动旧集群。

      • 如果您确实启动了新集群,它会写入共享文件,而使用旧集群是不安全的。在这种情况下,需要从备份中恢复旧集群。

环境

一些环境变量可用于为命令行选项提供默认值

PGBINOLD

旧的 PostgreSQL 可执行目录;选项 -b/--old-bindir

PGBINNEW

新的 PostgreSQL 可执行目录;选项 -B/--new-bindir

PGDATAOLD

旧的数据库集群配置目录;选项 -d/--old-datadir

PGDATANEW

新的数据库集群配置目录;选项 -D/--new-datadir

PGPORTOLD

旧集群端口号;选项 -p/--old-port

PGPORTNEW

新的集群端口号;选项 -P/--new-port

PGSOCKETDIR

在升级期间用于邮局主控套接字的目录;选项 -s/--socketdir

PGUSER

集群的安装用户名称;选项 -U/--username

注释

pg_upgrade 会创建各种工作文件,例如模式转储,存储在 pg_upgrade_output.d 中,该文件位于新集群的目录中。每次运行都会创建一个新的子目录,其名称采用按 ISO 8601 格式 (%Y%m%dT%H%M%S) 设置的时间戳命名,其中存储了所有生成的文件。 pg_upgrade_output.d 及其所含文件如果 pg_upgrade 成功完成,将会自动被删除;但在出现故障时,其中的文件可能会提供有用的调试信息。

pg_upgrade 在旧的新数据目录中启动瞬态的管理器。与这些管理器通信的临时 Unix 套接字文件默认在当前工作目录中进行。在某些情况下,当前目录的路径名可能会太长而无法成为一个有效的套接字名称。在那种情况下,可以使用 -s 选项将套接字文件放入具有较短路径名的目录中。为了确保安全,请确保该目录不被其他任何用户读取或写入。(Windows 不支持此功能。)

如果pg_upgrade 影响你的安装,它将报告所有失败、重建和重新索引案例;将自动生成重建表和索引的升级后脚本。如果你正在尝试自动化许多集群的升级,你应该会发现具有相同数据库架构的集群需要对所有集群升级执行相同的升级后步骤;这是因为升级后步骤基于数据库架构,而不是用户数据。

对于部署测试,创建旧集群仅架构的拷贝,插入虚拟数据并升级该数据。

pg_upgrade 不支持升级包含使用这些 reg* OID 引用系统数据类型的表列的数据库

regcollation
regconfig
regdictionary
regnamespace
regoper
regoperator
regproc
regprocedure

(regclassregroleregtype 可以升级。)

如果你希望使用链接模式并且不希望在新集群启动时修改你的旧集群,可以考虑使用克隆模式。如果该模式不可用,请复制旧集群并在链接模式中对其进行升级。要创建旧集群的有效副本,请使用 rsync 在服务器运行时创建旧集群的脏副本,然后关闭旧服务器并再次运行 rsync --checksum 更新副本中的所有更改,使其保持一致。(--checksum 是必需的,因为 rsync 每秒仅有一个文件修改时间粒度。)你可能希望排除某些文件,例如 postmaster.pid,如 第 25.3.4 节 中所述。如果你的文件系统支持文件系统快照或文件副本写时复制,你可以使用它对旧集群和表空间进行备份,尽管快照和副本必须同时创建或在数据库服务器关闭时创建。

另请参阅

initdbpg_ctlpg_dumppostgres