暂无图片
暂无图片
1
暂无图片
暂无图片
暂无图片

PostgreSQL 12.2 官方手册讲解(第 18 章之通过pg_upgrade升级一个PostgreSQL集簇)

PostgreSQL数据库工作学习随笔 2021-07-13
1898

pg_upgrade介绍

    pg_upgrade模块允许一个安装从一个 PostgreSQL主版本“就地”升级成另一个主版本。升级可以在数分钟内被执行,特别是使用--link模式时。它要求和上面的pg_dumpall相似的步骤,例如启动/停止 服务器、运行initdb。pg_upgrade 文档概述了所需的步骤。

    pg_upgrade(之前被称为pg_migrator) 允许存储在PostgreSQL数据文件中的数据被升级到一个较晚 的PostgreSQL主版本而无需进行主版本升级(例如从9.5.8到9.6.4或者从10.7到11.2)通常所需的数据转储/重载。对于次版本升级(例如从9.6.2到9.6.3或者从10.1到10.2)则不需要这个程序,此版本升级直接替换可执行文件就可以了。

    主 PostgreSQL 发行通常会加入新的特性,这些新特性常常会更改系统表的 布局,但是内部数据存储格式很少会改变。pg_upgrade 使用这一事实来通过创建新系统表并且重用旧的用户数据文件来执行快速升级。如果一个未来的主发行没有把数据存储格式改得让旧数据格式不可读取,这类 升级就用不上pg_upgrade。

    pg_upgrade会尽力(例如通过检查兼容的编译时设 置)确保新旧集簇在二进制上也是兼容的,包括 32/64 位二进制。保持 外部模块也是二进制兼容的也很重要,不过 pg_upgrade无法检查这一点。pg_upgrade 支持从 8.4.X 及其后版本升级到当前的 PostgreSQL主发布,包括快照和 beta发布。


pg_upgrade使用

下面是用pg_upgrade执行一次升级的步骤(12.6升级到13.2):

1. 移动旧集簇(可选)

    如果你在使用一个与版本相关的安装目录(例如 opt/PostgreSQL/12),你就不需要移动旧的集簇。图形化的安装程序会使用版本相关的安装目录。如果你的安装目录不是版本相关的(例如/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来确保所有设置都是兼容的。

注:我直接使用13.2的configure编译的新的 PostgreSQL 源码

./configure --prefix=/opt/pg13 --with-pgport=6666 --with-python --with-tcl --enable-nls --with-openssl --with-wal-blocksize=16

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

    安装新服务器的二进制文件和支持文件。pg_upgrade 会被包含在默认的安装中。对于源码安装,如果你希望把新服务器安装在一个自定义的位置, 可以使用prefix变量:

make prefix=/usr/local/pgsql.new install

注:我使用的是make world&make install安装,安装到的路径为configure指定的路径

4. 初始化新的 PostgreSQL 集簇

    使用initdb初始化新集簇。这里也要使用与 旧集簇相兼容的initdb标志。许多预编译的 安装程序会自动做这个步骤。这里没有必要启动新集簇。

注:/opt/pg13/bin/initdb -D /opt/pg13/pgdata/ --data-checksums

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

    把旧集簇使用的所有自定义共享对象文件(或者 DLL)安装到新集簇中,例如pgcrypto.so,不管它们是来自于 contrib还是某些其他源码。不要安装模式定义(例如CREATE EXTENSION pgcrypto),因为这些将会从旧集簇升级得到。还有,任何自定义的全文搜索文件(词典、同义词、辞典、停用词)也必须被复制到新集簇中。

6. 调整认证

    pg_upgrade将会多次连接到旧服务器和新服务器,因此 你可能想要在pg_hba.conf中把认证设置成 peer或者使用一个~/.pgpass文件。

7. 停止两个服务器

    确认两个数据库服务器都被停止使用,例如在 Unix 上可以:

/opt/pg12/bin/pg_ctl -D /opt/pg12/pgdata stop

/opt/pg13/bin/pg_ctl -D /opt/pg13/pgdata stop

直到后面的步骤之前,流复制和日志传送后备服务器可以保持运行。

8. 为后备服务器升级做准备

    如果正在使用小节步骤 10中给出的方法升级后备服务器,请对旧的主集簇和后备集簇

运行pg_controldata以验证旧的后备服务器已经完全追上。验证“Latest checkpoint

location”值在所有集簇中都匹配(如果旧后备服务器在旧的主服务器之前被关闭或者

如果旧的后备服务器仍在运行,则将会出现失配)。此外,在新的主集簇上的postgresql.conf文件中把wal_level改为replica。

9. 运行 pg_upgrade

    总是应该运行新服务器而不是旧服务器的pg_upgrade二进制文件。pg_upgrade要求制定新旧集簇的数据和可执行文件(bin)目录。 你也可以指定用户和端口值,以及你是否想要用链接或克隆来取代默认的复制行为对数据文件进行处理。

    如果你使用链接模式,升级将会快很多(不需要文件拷贝)并且将使用 更少的磁盘空间,但是在升级后一旦启动新集簇,旧集簇就无法被访问。 链接模式也要求新旧集簇数据目录位于同一个文件系统中(表空间和 pg_wal可以在不同的文件系统中)。 克隆模式提供了相同的速度以及磁盘空间优势,但不会导致新群集启动后旧群集不可用。 克隆模式还需要新旧数据目录位于同一文件系统中。 此模式仅在某些操作系统和文件系统上可用。

    --jobs选项允许多个 CPU 核心被用来复制/链接文件以及并行地转储和重载数据库模

式。这个选项一个比较好的值是 CPU 核心数和表空间数的最大值。这个选项可以显著

地减少升级运行在一台多处理器机器上的多数据库服务器的时间。

    一旦启动,pg_upgrade将验证两个集簇是否兼容并且执行升级。你可以使用pg_upgrade --check来只执行检查,这种模式即使在旧服务器还在运行时也能使用。pg_upgrade --check也将列出任何在更新后需要做的手工调整。如果你将要使用链接或克隆模式,你应该使用--link(使用硬链接来代替将文件拷贝到新集簇)

或--clone选项(文件克隆仅在某些操作系统和文件系统上得到支持。如果选中但不被支持,则pg_upgrade运行将会出错。目前,它支持在Linux(内核4.5或更高版本)上的Btrfs和XFS(在文件系统创建reflink支持),以及macOS上的APFS。)

和--check一起来启用链接模式相关的检查。pg_upgrade要求在当前目录中的写权限。显然,没有人可以在升级期间访问这些集簇。pg_upgrade 默认会在端口50432上运行服务器来避免意外的客户端连接。在做升级时, 可以对两个集簇使用相同的端口号,因为新旧集簇不会在同时被运行。不过, 在检查一个旧的运行中服务器时,新旧端口号必须不同。如果在恢复数据库模式时发生错误,pg_upgrade将会退出 并且你必须按照下文步骤16中所说的恢复旧集簇。要再次尝试pg_upgrade,你将需要修改旧集簇,这样pg_upgrade 模式会成功恢复。如果问题是一个 contrib模块, 你可能需要从旧集簇中卸载该模块并且在升级后重新把它安装在新集簇中,不过 这样做的前提是该模块没有被用来存储用户数据。

使用link升级成功:

传输优化器统计信息:

删除就集簇的数据文件(可选):

访问数据库:


注:

新的数据库集簇下不能有任何其他表否则会报错,如下:

New cluster database "postgres" is not empty: found relation "public.test"

新旧集群使用相同的超级用户创建集群

参数文件需要重新配置

10. 升级流复制和日志传送后备服务器

    如果使用链接模式并且有流复制(见第 26.2.5 节 )或者日志 传送(见第 26.2 节)后备服务器,你可以遵照下面的 步骤对它们进行快速的升级。你将不用在这些后备服务

器上运行 pg_upgrade,而是在主服务器上运行rsync。到这里还不要启动任何服务器。

    如果你没有使用链接模式、没有或不想使用rsync或者想用一种更容易的解决方案,请跳过这一节中的过程并且在pg_upgrade完成并且新的主集簇开始运行后重建后备服务器。

a. 在后备服务器上安装新的 PostgreSQL 二进制文件

    确保新的二进制和支持文件被安装在所有后备服务器上。

b. 确保不存在新的后备机数据目录

    确保新的后备机数据目录不存在或者为空。如果运行过initdb,请删除后备服务

器的新数据目录。

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

    在新的后备机上安装和新的主集簇中相同的自定义共享对象文件。

d. 停止后备服务器

    如果后备服务器仍在运行,现在使用上述的指令停止它们。

e. 保存配置文件

    从旧后备机的配置目录保存任何需要保留的配置文件,例如postgresql.conf、pg_hba.conf, 因为这些文件在下一步中会被重写或者移除。

f. 运行rsync

    在使用链接模式时,后备服务器可以使用rsync快速升级。为了实现这一点,在主服务器上一个高于新旧数据库集簇目录的目录中为每个后备服务器运行这个命令:

rsync --archive --delete --hard-links --size-only --no-inc-recursive

old_cluster new_cluster remote_dir

    其中old_cluster和new_cluster是相对于主服务器上的当前目录的,而remote_dir是后备服务器上高于新旧集簇目录的一个目录。在主服务器和后备服务器上指定目录之下的目录结构必须匹配。指定远程目录的详细情况请参考rsync的手册,例如:

rsync --archive --delete --hard-links --size-only --no-inc-recursive /

opt/PostgreSQL/9.5 \

/opt/PostgreSQL/9.6 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_9.5_201510051 \

/vol1/pg_tblsp/PG_9.6_201608131 standby.example.com:/vol1/pg_tblsp

    如果你已经把pg_wal放在数据目录外面,也必须在那些目录上运行rsync。

g. 配置流复制和日志传送后备服务器

    为日志传送配置服务器(不需要运行pg_start_backup() 以及pg_stop_backup()或

者做文件系统备份,因为从属机仍在与主机同步)。

注:步骤10为官方文档内容,服务器环境有限,未做测试

11. 恢复 pg_hba.conf

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

12. 启动新服务器

    现在可以安全地启动新的服务器,并且可以接着启动任何rsync过的后备服务器。

13. 升级后处理

    如果需要做任何升级后处理,pg_upgrade 将在完成后发出警告。它也将生成必须由管理员运行的脚本文件。这些脚本文件将连接到每一个需要做升级后处理的数据库。

一个脚本应该这样运行:

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

    这些脚本可以以任何顺序运行并且在运行之后立即删除。

14. 统计信息

    由于pg_upgrade并未传输优化器统计信息,在升级的尾声你将被指示运行一个命令来生成这些信息。你可能需要设置连接参数来匹配你的新集簇。

15. 删除旧集簇

    一旦你对升级表示满意,你就可以通过运行 pg_upgrade完成时提到的脚本来删除旧集簇的数据目录(如果在旧数据目录中有用户定义的表空间就不可能实现自动删除)。你也可以删除旧安装目录(例如bin、share)。

16. 恢复到旧集簇

    在运行pg_upgrade之后,如果你希望恢复到旧集簇,有几个选项:

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

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

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

    • 如果pg_upgrade在链接启动之前中止,旧群集没有被修改,它可以重新启动。

    • 如果你没有启动新集群,旧集群没有被修改,当链接启动时,一个.old后缀会附加到$PGDATA/global/pg_control。 如果要重用旧集群,从$PGDATA/global/

pg_control移除.old后缀;你就可以重启旧集群。

    • 如果你已经启动新群集,它已经写入了共享文件,并且使用旧群集会不安全。这种

情况下,需要从备份中还原旧群集。


后续会介绍如何通过复制升级数据。

文章转载自PostgreSQL数据库工作学习随笔,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论