选择 打开 改范围 完整检索页

pgsql.cc 提供对 postgresql.org 官网内容的中文翻译,由 Pigsty 团队维护。

受支持版本: 当前版本 (18) / 17 / 16 / 15 / 14
测试与开发版本: 19 / devel
不受支持的版本: 13 / 12 / 11 / 10 / 9.6 / 9.5 / 9.4 / 9.3 / 9.2 / 9.1 / 9.0
历史版本PostgreSQL 9.4 已于 2020 年 2 月结束社区维护,本页译文保留供仍在使用旧版本的读者参考。新系统请看当前版本

pg_upgrade

pg_upgrade — 升级一个PostgreSQL服务器实例

大纲

pg_upgrade -b oldbindir -B newbindir -d olddatadir -D newdatadir [option...]

描述

pg_upgrade(以前称为 pg_migrator)允许将存储在 PostgreSQL 数据文件中的数据升级到更新的 PostgreSQL主版本,而无需执行主版本升级通常所需的数据转储/重新装载, 例如从 8.4.7 升级到 PostgreSQL 的当前主版本。次版本升级不需要使用它, 例如从 9.0.1 升级到 9.0.4。

PostgreSQL 主版本会定期增加新特性,这些特性常常会改变系统表的布局, 但内部数据存储格式很少改变。pg_upgrade利用这一点, 通过创建新的系统表并直接重用旧的用户数据文件来快速完成升级。如果未来某个 主版本改变了数据存储格式,致使旧数据格式无法读取,那么 pg_upgrade就不能用于这类升级。(社区会尽量避免这种情况。)

pg_upgrade会尽最大努力确保新旧集簇在二进制上兼容, 例如会检查兼容的编译时设置,包括 32/64 位二进制程序。任何外部模块也同样必须 二进制兼容,这一点很重要,但 pg_upgrade 无法检查。

pg_upgrade 支持从 8.3.X 及更高版本升级到当前 PostgreSQL主版本,包括快照版和 alpha 版。

选项

pg_upgrade接受下列命令行参数:

-b bindir
--old-bindir=bindir

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

-B bindir
--new-bindir=bindir

新 PostgreSQL 可执行文件目录;环境变量 PGBINNEW

-c
--check

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

-d datadir
--old-datadir=datadir

旧集簇数据目录;环境变量 PGDATAOLD

-D datadir
--new-datadir=datadir

新集簇数据目录;环境变量 PGDATANEW

-j
--jobs

要使用的并发进程或线程数

-k
--link

使用硬链接而不是把文件复制到新集簇

-o options
--old-options options

将直接传递给旧 postgres 命令的选项

-O options
--new-options options

将直接传递给新 postgres 命令的选项

-p port
--old-port=port

旧集簇端口号;环境变量 PGPORTOLD

-P port
--new-port=port

新集簇端口号;环境变量 PGPORTNEW

-r
--retain

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

-U username
--username=username

集簇超级用户名称;环境变量 PGUSER

-v
--verbose

启用详细的内部日志记录

-V
--version

显示版本信息,然后退出

-?
--help

显示帮助,然后退出

使用

使用pg_upgrade执行升级的步骤如下:

  1. 移动旧集簇(可选)

    如果你使用的是带版本号的安装目录,例如 /opt/PostgreSQL/9.1,则不必移动旧集簇。 图形化安装程序都使用带版本号的安装目录。

    如果你的安装目录不是带版本号的,例如 /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 二进制文件

    安装新服务器的二进制文件和支持文件。

    对于源码安装,如果你希望把新服务器安装到自定义位置,可以使用 prefix 变量:

    make prefix=/usr/local/pgsql.new install
    
  4. 安装 pg_upgrade 和 pg_upgrade_support

    在新的 PostgreSQL 安装中安装pg_upgrade二进制文件和pg_upgrade_support库。

  5. 初始化新的 PostgreSQL 集簇

    使用 initdb 初始化新集簇。这里同样要使用与旧集簇匹配的兼容 initdb 标志。许多预构建的安装程序会自动执行该步骤。 无需启动新集簇。

  6. 安装自定义共享对象文件

    将旧集簇使用的所有自定义共享对象文件(或 DLL)安装到新集簇中,例如 pgcrypto.so,无论它们来自 contrib 还是其他来源。不要安装模式定义,例如 CREATE EXTENSION pgcrypto,因为这些会从旧集簇升级过来。 另外,所有自定义全文检索文件(词典、同义词、词库、停用词)也必须复制到新集簇。

  7. 调整认证

    pg_upgrade 会多次连接旧服务器和新服务器,因此你可能希望将认证设置为 peer(在 pg_hba.conf 中),或者使用 ~/.pgpass 文件(见 第 31.15 节)。

  8. 停止两个服务器

    确保两个数据库服务器都已停止。例如,在 Unix 上使用:

    pg_ctl -D /opt/PostgreSQL/8.4 stop
    pg_ctl -D /opt/PostgreSQL/9.0 stop
    

    或者在 Windows 上使用正确的服务名:

    NET STOP postgresql-8.4
    NET STOP postgresql-9.0
    

    NET STOP pgsql-8.3  (PostgreSQL 8.3 及更早版本使用不同的服务名)
    
  9. 运行 pg_upgrade

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

    如果使用链接模式,升级将快得多(无需复制文件)且占用更少磁盘空间,但一旦在升级后启动 新集簇,就无法再访问旧集簇。链接模式还要求新旧集簇的数据目录位于同一文件系统中。 (表空间和 pg_xlog 可以位于不同文件系统中。)完整选项列表请参阅pg_upgrade --help

    --jobs选项允许使用多个 CPU 核心复制/链接文件,并行转储和重新装载数据库模式;一个不错的起始值是 CPU 核心数与表空间数量中的较大值。对于运行在多处理器机器上的多数据库服务器,此选项可以显著减少升级时间。

    Windows 用户必须先登录管理员帐号,然后以 postgres 用户身份启动 shell,并设置正确的路径:

    RUNAS /USER:postgres "CMD.EXE"
    SET PATH=%PATH%;C:\Program Files\PostgreSQL\9.0\bin;
    

    然后运行 pg_upgrade,并用引号括起目录,例如:

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

    启动后,pg_upgrade会验证两个集簇是否兼容,然后执行升级。你可以使用 pg_upgrade --check 仅执行检查,即使旧服务器仍在运行。pg_upgrade --check还会概述升级后需要手工进行的调整。如果打算使用链接模式,应将 --link 选项与 --check 一起使用,以启用链接模式的专用检查。pg_upgrade需要对当前目录具有写权限。

    显然,在升级期间不应有人访问这些集簇。pg_upgrade 默认会在 50432 端口上运行服务器,以避免意外的客户端连接。升级时可以让两个集簇使用相同 的端口号,因为新旧集簇不会同时运行。不过,在检查仍在运行的旧服务器时,新旧端口号必须不同。

    如果在恢复数据库模式时发生错误,pg_upgrade 将退出,你必须按照下文 步骤 14 所述回退到旧集簇。若要再次尝试 pg_upgrade,你需要修改旧集簇,使 pg_upgrade 的模式恢复步骤能够成功完成。 如果问题出在某个 contrib 模块,而该模块并未用于存储用户数据, 则你可能需要先从旧集簇卸载这个 contrib 模块,并在升级后将其安装到新集簇。

  10. 恢复 pg_hba.conf

    如果你修改了 pg_hba.conf,请恢复其原始设置。 也可能需要调整新集簇中的其他配置文件以匹配旧集簇,例如 postgresql.conf

  11. 升级后处理

    如果需要任何升级后处理,pg_upgrade 在完成时会发出警告。它还会生成必须由管理员运行的脚本文件。这些脚本会连接到每个需要升级后处理的数据库。每个脚本应通过以下方式运行:

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

    这些脚本可以按任意顺序运行,运行完毕后即可删除。

    小心

    一般来说,在重建脚本运行完成之前访问其中引用的表是不安全的;这样做可能产生错误结果 或较差的性能。未在重建脚本中引用的表则可以立即访问。

  12. 统计信息

    由于优化器统计信息不会由pg_upgrade传输,升级结束时你会被要求运行命令来重新生成这些信息。你可能需要设置连接参数以匹配新集簇。

  13. 删除旧集簇

    一旦你确认升级结果令人满意,就可以运行 pg_upgrade 完成时提到的脚本, 删除旧集簇的数据目录。(如果旧数据目录中包含用户定义的表空间,则无法自动删除。) 你也可以删除旧的安装目录(例如 binshare)。

  14. 恢复到旧集簇

    如果在运行 pg_upgrade 之后,你想恢复到旧集簇,可以选择以下几种方法:

    • 如果使用了 --check 选项,旧集簇不会被修改;可以重新启动。

    • 如果--link选项没有被使用,旧集簇就未被修改,可以重新启动。

    • 如果使用了 --link 选项,新旧集簇可能共享数据文件:

      • 如果 pg_upgrade 在开始建立链接之前就已中止, 旧集簇不会被修改;可以重新启动。

      • 如果你没有启动新集簇,则旧集簇没有被修改,只是在开始建立链接时, 会把一个 .old 后缀附加到 $PGDATA/global/pg_control。要重新使用旧集簇,请移除 .old 这个附加在 $PGDATA/global/pg_control 上的后缀;随后即可重新启动旧集簇。

      • 如果你启动了新集簇,它就已经写入了共享文件,此时再使用旧集簇是不安全的。 在这种情况下,旧集簇必须从备份恢复。

注解

pg_upgrade不支持升级包含下列reg* OID 引用系统数据类型的数据库:regprocregprocedureregoperregoperatorregconfigregdictionary。(regtype可以升级。)

凡是会影响你安装环境的失败、重建和重新索引情况,pg_upgrade 都会报告;用于重建表和索引的升级后脚本也会自动生成。如果你试图自动化升级很多集簇, 你会发现具有相同数据库模式的集簇在所有升级中需要相同的升级后步骤;这是因为升级后步骤 依据的是数据库模式,而不是用户数据。

为了测试部署,请创建旧集簇的纯模式副本,插入虚拟数据,然后对其升级。

如果正在升级PostgreSQL 9.2 之前的集簇,而且它使用了只包含配置文件的目录,就必须把实际数据目录的位置传给pg_upgrade,并把配置目录的位置传给服务器,例如-d /real-data-directory -o '-D /configuration-directory'

如果旧服务器早于 9.1,而且使用非默认的 Unix 域套接字目录,或者其默认目录与新集簇的默认目录不同,请将PGHOST设置为旧服务器的套接字位置。(这与 Windows 无关。)

日志传送备库服务器(第 25.2 节)无法被升级,因为服务器必须允许写入。最简单的方法是升级主库,然后用rsync重建备库。你可以在主库停机时运行rsync,也可以把它作为基础备份(第 24.3.2 节)的一部分,这会覆盖旧的备库集簇。

如果你想使用链接模式,又不希望在启动新集簇时修改旧集簇,可以先复制旧集簇,再对该副本使用链接模式升级。要创建旧集簇的有效副本, 可在服务器运行时使用 rsync 创建旧集簇的脏拷贝,然后关闭旧服务器, 再运行 rsync,把所有变更同步到该副本,使其达到一致状态。你可能还想排除某些文件,例如 postmaster.pid,如 第 24.3.3 节 所述。 如果你的文件系统支持文件系统快照或写时复制文件副本, 也可以用这些方式备份旧集簇和表空间,不过快照和副本必须同时创建,或者在数据库服务器关闭时创建。

从 PostgreSQL 8.3 升级时的限制

从 PostgreSQL 8.3升级比从更新的 PostgreSQL 版本升级有额外的限制。例如,如果一个用户列被定义为:

  • tsquery数据类型

  • name数据类型且不是第一列

则 pg_upgrade 无法用于从 8.3 升级。

你必须删除所有这样的列并手工升级它们。

如果数据库中安装了ltree contrib 模块,pg_upgrade 将无法工作。

如果出现下列情况,pg_upgrade 将要求重建表:

  • 某个用户列的数据类型为tsvector

如果出现下列情况,pg_upgrade 将要求重新索引:

  • 某个索引为 hash 或 GIN 类型

  • 某个索引使用了bpchar_pattern_ops

此外,在PostgreSQL 8.3 之后,默认的日期时间存储格式改为了整数。pg_upgrade 会检查新旧集簇使用的日期时间存储格式是否匹配。请确保你的新集簇在构建时使用了 configure 选项--disable-integer-datetimes

对于 Windows 用户,请注意,由于图形安装程序和 MSI 安装程序使用的整数日期时间设置不同,只能从安装程序发行版的 8.3 版本升级到安装程序发行版的 8.4 或更高版本。无法从 MSI 安装程序升级到新的图形安装程序。

提交更正

译文有误、术语不当或页面显示问题,请到译文仓库 pgsty/pgdoc 报告译文问题。 英文原文本身的问题,请在当前版本的对应页面向上游反馈;上游不再修订已结束维护的版本。