ThinkChat2.0新版上线,更智能更精彩,支持会话、画图、阅读、搜索等,送10W Token,即刻开启你的AI之旅 广告
# pg_upgrade ## Name pg_upgrade -- 升级 PostgreSQL 数据库实例 ## Synopsis `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` `_old_bindir_``--old-bindir=``_old_bindir_` 旧的数据实例的可执行文件目录; 环境变量 `PGBINOLD` `-B` `_new_bindir_` `--new-bindir=``_new_bindir_` 新的数据实例的可执行文件目录; 环境变量 `PGBINNEW` `-c` `--check` 仅检查实例,不做任何数据更新 `-d` `_old_datadir_` `--old-datadir=``_old_datadir_` 旧的群集数据目录;环境变量`PGDATAOLD` `-D` `_new_datadir_` `--new-datadir=``_new_datadir_` 新的群集数据目录;环境变量`PGDATANEW` `-j` `--jobs` 同时使用的进程或者线程数 `-k` `--link` 使用硬链接替代拷贝文件到新的数据库实例 (在windows使用NTFS的接点) `-o` `_options_` `--old-options` `_options_` options to be passed directly to the old `postgres` command `-O` `_options_` `--new-options` `_options_` options to be passed directly to the new `postgres` command `-p` `_old_port_number_` `--old-port=``_old_portnum_` 旧数据库实例的端口;环境变量`PGPORTOLD` `-P` `_new_port_number_` `--new-port=``_new_portnum_` 新数据库实例的端口;环境变量`PGPORTNEW` `-r` `--retain` 即使在升级成功也保存相关的SQL和日志文件。 `-u` `_user_name_` `--user=``_user_name_` 数据实例的超级管理员名; 环境变量 `PGUSER` `-v` `--verbose` 启用详细的内部日志信息 `-V` `--version` 打印版本信息,然后退出 `-?` `-h` `--help` 显示当前帮助,然后退出 ## 用法 用 pg_upgrade进行升级的步骤: 1. **选择性的移动实例的安装目录** 如果你用了指定版本的安装目录,例如 `/opt/PostgreSQL/9.1`, 你不需要再移动 旧的安装目录。图形化安装工具都是指定安装目录的。 如果你的安装目录不是版本指定的,例如 `/usr/local/pgsql`, 这就有必要 移动当前的安装目录,这样就避免影响了新的 PostgreSQL 的安装。 当 PostgreSQL 数据库服务停止后, 重命令PostgreSQL的安装 目录的操作是安全的;假如旧安装目录是 `/usr/local/pgsql`, 你可以用命令: ``` mv /usr/local/pgsql /usr/local/pgsql.old ``` 来重命令当前目录名。 2. **用源码安装,构建一个新的版本** 用兼容旧的数据库实例`configure` 选项来构建新的PostgreSQL。在开始升级之前 pg_upgrade 将会检查`pg_controldata` 来确保所有的设置都兼容。 3. **安装新的二进制文件** 安装新服务器的二进制可执行文件和支持文件。 用源码安装时,如果你想要在自定义目录安装新服务器,可以使用 `prefix` 变量: ``` gmake prefix=/usr/local/pgsql.new install ``` 4. **Install pg_upgrade and pg_upgrade_support** 在新PostgreSQL的安装中,安装 pg_upgrade 二进制文件 and pg_upgrade_support库文件 。 5. **初始化新的数据库实例** 使用`initdb`命令初始化新的数据库实例。 并且,要用兼容的旧数据库实例的`initdb` 选项 。 很多预构建安装会自动完成这一部。不需要去启动新的数据库实例。 6. **安装自定义的共享对象文件** 安装所以旧数据库实例用到的自定义共享对象文件(或者是DLL文件), 例如 `pgcrypto.so`, 无论他们来自 `contrib` 或者其它的源。 不需要安装一类模式的定义, 例如`pgcrypto.sql`, 因为这些也会从旧数据库实例中升级。 7. **调整连接认证** `pg_upgrade` 会数次连到新旧数据库实例,所以你修改 `pg_hba.conf`,可以把认证设置成 `trust` 或者是 `peer` ,另外也可以使用 `md5` 的认证方式, 同时使用 `~/.pgpass`密码文件 (参考 [Section 31.15](#calibre_link-457)). 8. **停止新旧数据库** 确保两个数据库都停止使用, 在类Unix操作系统中使用 例如: ``` pg_ctl -D /opt/PostgreSQL/8.4 stop pg_ctl -D /opt/PostgreSQL/9.0 stop ``` 在Windows中,使用windows可用的服务名: ``` NET STOP postgresql-8.4 NET STOP postgresql-9.0 ``` 或者 ``` NET STOP pgsql-8.3 (8.3和更早版本的PostgreSQL 使用了不同的服务器) ``` 9. **运行 pg_upgrade** 运行新数据库的可执行命令 pg_upgrade , 而不是旧数据库的。 pg_upgrade 需要指定新旧数据库实例的数据目录和可执行的 (`bin`) 目录。 当然你还可以指定用户和端口,指定是否使用数据硬链接代替使用 数据复制(默认方式)。 如果你使用链接模式,升级将会非常快(没有文件拷贝)并且占用更少的硬盘,但是你不能 再访问你的旧数据库当你升级完成启动新的数据库实例。 链接模式还需要新旧数据库 数据目录使用相同的文件系统。(表空间和 `pg_xlog` 可以在不同的 文件系统。) 参考 `pg_upgrade --help` 查看完整的帮助选项列表。 `--jobs` 选项可以在拷贝/链接数据文件时使用多CPU核心并且可以并行 的还原数据库模式;一个好的值是CPU核数和表空间的最大值。在一个多核数据库 机器上升级一个多数据库服务器时这个选项能大量的节约时间。 For Windows users, you must be logged into an administrative account, and 对于Windows用户来说,你必要登录一个管理员的帐号,并且用 `postgres` 用户来启动一个终端设置可用的PATH ``` 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` 将会退出你必需参照 [step 14](#calibre_link-2341)的概要信息还原旧实例 再一次使用`pg_upgrade` , 你可能需要修改旧实例以让旧数据库模式 升级成功。如果问题出现在某个外部模块上,你可能需要从旧实例上卸载这些外部模块 然后在升级成功后再在新实例上安装它们,假设模块没有被用于储存用户数据。 10. **还原 `pg_hba.conf`** 如果你修改`pg_hba.conf` 成 `trust`的方式, 还原它的原来的认证设置。 还有可能需要去调整其它的配置文件去和旧的数据库 实例相匹配,例如。`postgresql.conf`. 11. **升级后的处理** 如果有升级后续操作需要执行,pg_upgrade会在完成后发布出警告信息。 同时它会生成由管理员运行脚本文件。 脚本会连到新旧数据库执行后续操作。 脚本可以用下面命令执行: ``` psql --username postgres --file script.sql postgres ``` 脚本可以任意顺序执行,执行完后可以被删除。 **Caution** 通常情况下在重建脚本运行结束之前不允许访问被引用的表;这样做可能会出现 意想不到的错误结果或者是性能不佳 。不引用的表可以被立限访问。 12. **统计** 因为优化统计结果不会被`pg_upgrade`传递, 你需要指定去运行命令去在升级 完成后生成一些新的信息。你可能需要设置连接参数去匹配新的数据库实例。 13. **删除旧的数据库实例** 当`pg_upgrade` 成功的升级完成后,你可能要运行脚本的 方法删除旧的数据库实例的数据目录你可以删除旧安装目录 (例如。 `bin`, `share`)。 14. **还原到旧实例** 如果,运行`pg_upgrade`后, 你希望回复到旧实例, 下面是一些选项: * 如果你运行了加`--check` 参数的`pg_upgrade` ,不会对旧数据实例产生影响可以随时更新实用。 * 如果你运行了加`--link`参数的 `pg_upgrade` 数据文件会被新旧数据实例所共用,如果你启动了新数据实例,新的 数据库会写到那些共享文件上,这对旧实例是不安全的。 * 如果你运行了_不加_`--link`参数的 `pg_upgrade` 或者没有启动新的数据库,旧实例并没有被修改过,如果链接开始, `.old`后缀会出现在 `$PGDATA/global/pg_control`目录下。 为了重新旧数据实例,可以从`$PGDATA/global/pg_control` 目录下移除`.old`后缀的文件;然后你可以重启旧实例。 ## 注意事项 pg_upgrade不支持包含有`reg*` 类型的OID-引用 比如 以下类型: `regproc`, `regprocedure`, `regoper`, `regoperator`, `regconfig`, and `regdictionary`. (`regtype` 可以被升级。) 所有失败, 重建, 和重建索引会影响到你升级都会被pg_upgrade报告。 升级后的重建表和索引会自动生成。如果你尝试自动升级多个实例,你应该找到 相同的数据模式需要相同的升级后步骤对所以的实例升级;这是因为升级后的步骤 是基于数据库模式的,而不是用户数据。 部署测试,可以创建一个只读的模式从旧数据实例复制,插入一些虚拟的数据, 然后升级他们。 如果你升级PostgreSQL 9.2版本之前只用一个仅配置目录的 的数据库,你必要传递真的数据目录给pg_upgrade,并且给数据库传递配置目录, 例如。 `-d /real-data-directory -o '-D /configuration-directory'`。 如果用一个9.1之前用了非默认的Unix域socket目录或者默认的位置和新实例 默认位置不一致,要设置 `PGHOST`来指定旧数据库的socket位置。 (在Windows下不需要。) 一个日志同步的数据库([Section 25.2](#calibre_link-1133)) 不能被升级原因是 升级数据库必需要允许写。很简单的方式是升级方库然后用rsync去重新建 备份。你可以运行`rsync` 当主库停用后,或者作为一次基础备份 ([Section 24.3.2](#calibre_link-1632))去覆盖旧的数据库备份。 如果你想要用link方式并且当新实例启动后你不想要你的旧数据库实例数据被修改 用`rsync` 从运行中的旧实例新建一个脏的数据复制,然后关闭旧实例 再一次运行`rsync` 保证所有的数据更改保持一致的。你可能需要 排除一些文件,例如。`postmaster.pid`, 还有在 [Section 24.3.3](#calibre_link-1633)提到的文件。 ### 从PostgreSQL 8.3升级的局限性 _从_ PostgreSQL 8.3 升级有一些额外的条件没有被提及 当升级到以后的PostgreSQL发行版本。 举个例子,在8.3版本中如果用户字段中 定义了: * 一个 `tsquery` 数据类型 * 数据类型`name` 并不是第一个字段pg_upgrade将不支持升级。 你必需要删除任何这样的字段并且手动升级他们。 如果`ltree`模块被安装到数据库中,pg_upgradebu将不支持。 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安装程序 到升级新的图形化安装程序中。 ## 参考 [initdb](#calibre_link-542), [pg_ctl](#calibre_link-544), [pg_dump](#calibre_link-437), [postgres](#calibre_link-1033)