pgsql.cc 提供对 postgresql.org 官网内容的中文翻译,由 Pigsty 团队维护。
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 old_bindir--old-bindir=old_bindir旧集簇的可执行文件目录;环境变量 OLDBINDIR
-B new_bindir--new-bindir=new_bindir新集簇的可执行文件目录;环境变量 NEWBINDIR
-c--check只检查集簇,不更改任何数据
-d old_datadir--old-datadir=old_datadir旧集簇的数据目录;环境变量 OLDDATADIR
-D new_datadir--new-datadir=new_datadir新集簇的数据目录;环境变量 NEWDATADIR
-g--debug启用调试
-G debug_filename--debugfile=debug_filename将调试活动输出到文件
-k--link使用硬链接而不是将文件复制到新集簇
-l log_filename--logfile=log_filename将会话活动记录到文件
-p old_port_number--old-port=old_portnum旧集簇的端口号;环境变量 PGPORT
-P new_port_number--new-port=new_portnum新集簇的端口号;环境变量 PGPORT
-u user_name--user=user_name集簇超级用户名称;环境变量 PGUSER
-v--verbose启用详细输出
-V--version显示版本信息,然后退出
-?-h--help显示帮助,然后退出
移动旧集簇(可选)
如果你使用的是带版本号的安装目录,例如 /opt/PostgreSQL/8.4,则无需移动旧集簇。 一键安装程序都使用带版本号的安装目录。
如果你的安装目录不是带版本号的,例如 /usr/local/pgsql, 就必须移动当前的 PostgreSQL 安装目录,以免它干扰新的 PostgreSQL 安装。当前的 PostgreSQL 服务器关闭后,就可以安全地重命名 PostgreSQL 安装目录。假设旧目录是 /usr/local/pgsql, 你可以这样做:
mv /usr/local/pgsql /usr/local/pgsql.old
以上命令会重命名该目录。
对于源码安装,编译新版本
使用与旧集簇兼容的 configure 标志编译新的 PostgreSQL 源码。 pg_upgrade 会在开始升级前检查 pg_controldata, 以确保所有设置都兼容。
安装新的 PostgreSQL 二进制文件
安装新服务器的二进制文件和支持文件。两个集簇可以使用相同的 端口号(通常是 5432),因为新旧集簇不会同时运行。
对于源码安装,如果你希望把新服务器安装到自定义位置,可以使用 prefix 变量:
gmake prefix=/usr/local/pgsql.new install
安装 pg_upgrade 和 pg_upgrade_support
把 pg_upgrade 二进制和 pg_upgrade_support 库安装到新的 PostgreSQL 集簇中。
初始化新的 PostgreSQL 集簇
使用 initdb 初始化新集簇。这里同样要使用与旧集簇匹配的兼容 initdb 标志。许多预构建的安装程序会自动执行该步骤。 无需启动新集簇。
安装自定义共享对象文件
将旧集簇使用的所有自定义共享对象文件(或 DLL)安装到新集簇中,例如 pgcrypto.so,无论它们来自 contrib 还是其他来源。不要安装模式定义,例如 pgcrypto.sql,因为这些会从旧集簇升级过来。
调整认证
pg_upgrade 会多次连接旧服务器和新服务器,因此你可能希望将认证设置为 peer(在 pg_hba.conf 中),或者使用 ~/.pgpass 文件(见 第 31.14 节)。
停止两个服务器
确保两个数据库服务器都已停止。例如,在 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 及更早版本使用不同的服务名)
运行 pg_upgrade
始终运行新服务器的 pg_upgrade 二进制,而不是旧服务器的。 pg_upgrade 需要指定新旧集簇的数据目录和可执行文件 (bin)目录。你还可以指定用户和端口值,以及是否希望链接数据而不是复制(默认)。
如果使用链接模式,升级将快得多(无需复制文件),但一旦在 升级后启动新集簇,就无法再访问旧集簇。链接模式还要求新旧 集簇的数据目录位于同一文件系统中。完整选项列表请参阅 pg_upgrade --help。
对于 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 还会概述升级后需要手工调整的内容。pg_upgrade 要求对当前目录有写权限。
显然,升级期间不应有人访问集簇。考虑为旧集簇和新集簇使用非默认端口号(例如 50432),以避免升级期间意外的客户端连接。
如果在恢复数据库模式时发生错误,pg_upgrade 将退出,你必须按照下文 步骤 14 所述回退到旧集簇。若要再次尝试 pg_upgrade,你需要修改旧集簇,使 pg_upgrade 的模式恢复步骤能够成功完成。 如果问题出在某个 contrib 模块,而该模块并未用于存储用户数据, 则你可能需要先从旧集簇卸载这个 contrib 模块,并在升级后将其安装到新集簇。
恢复 pg_hba.conf
如果修改过 pg_hba.conf,请恢复其原始设置。
升级后处理
如果需要任何升级后处理,pg_upgrade 在完成时会发出警告。它还会生成必须由管理员运行的脚本文件。这些脚本会连接到每个需要升级后处理的数据库。每个脚本应通过以下方式运行:
psql --username postgres --file script.sql postgres
这些脚本可以按任意顺序运行,运行完毕后即可删除。
一般来说,在重建脚本运行完成之前访问其中引用的表是不安全的;这样做可能产生错误结果 或较差的性能。未在重建脚本中引用的表则可以立即访问。
统计信息
由于优化器统计信息不会被 pg_upgrade 传送,在升级结束时你会被指示运行一个命令重新生成这些信息。
删除旧集簇
对升级结果满意后,可以运行 pg_upgrade 完成时提到的脚本删除旧集簇的 数据目录。还可以删除旧的安装目录 (例如 bin、share)。
恢复到旧集簇
如果在运行 pg_upgrade 之后希望回退到旧集簇,有以下 几种选择:
如果你运行 pg_upgrade 时使用了 --check,旧集簇未做任何修改,可以随时 重新使用它。
如果你运行 pg_upgrade 时使用了 --link,数据文件由新旧集簇共享。如果你 已经启动过新集簇,新服务器已写入这些共享文件,再使用旧 集簇就不安全了。
如果你运行 pg_upgrade 时没有使用 --link,或者没有启动过新服务器,那么旧集簇除了在 $PGDATA/global/pg_control 以及可能还有表空间目录上追加了 .old 后缀之外未被修改。要重新使用旧集簇,请移除 $PGDATA/global/pg_control 上的 .old 后缀,并且如果是升级到 8.4 或更早版本,还要删除升级创建的表空间目录并移除表空间目录名上的 .old 后缀;然后就可以重启旧集簇。
从 PostgreSQL 8.3 升级存在从更高 PostgreSQL 版本升级时所没有的额外限制。例如,如果有用户列定义为下列类型,pg_upgrade 将无法用于从 8.3 升级:
tsquery 数据类型
name 数据类型且不是第一列
你必须删除所有这样的列并手工升级它们。
如果数据库中安装了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 安装程序升级到一键 安装程序。
pg_upgrade不支持升级包含下列reg* OID 引用系统数据类型的数据库:regproc、regprocedure、regoper、regoperator、regconfig和regdictionary。(regtype可以升级。)
所有失败、重建和重新索引的情形,只要影响你的安装,都会被 pg_upgrade 报告;用于重建表和索引的升级后脚本会自动生成。
为了测试部署,请创建旧集簇的纯模式副本,插入虚拟数据,然后对其升级。
如果你想使用链接模式,又不希望旧集簇在新集簇启动后被修改,可以先制作旧集簇的一个副本,然后用链接模式升级该副本。要制作一个有效的旧集簇副本,可以在服务器运行时用 rsync 创建旧集簇的“脏”副本,然后关闭旧服务器并再次运行 rsync,用所有变更更新副本使其保持一致。
译文有误、术语不当或页面显示问题,请到译文仓库 pgsty/pgdoc 报告译文问题。 英文原文本身的问题,请在当前版本的对应页面向上游反馈;上游不再修订已结束维护的版本。