大家好,我是只谈技术不剪发的 Tony 老师。对于企业而言,将数据库系统升级到新版本通常可以获得更好的性能、更多的功能、最新的安全补丁和错误修复等。因此,本文就来介绍一下 PostgreSQL 数据库版本升级的 3 种常用方案。
升级方案概述
PostgreSQL 版本号由主要版本和次要版本组成。例如,PostgreSQL 12.4 中的 12 是主要版本,4 是次要版本;PostgreSQL 10.0 之前的版本由 3 个数字组成,例如 9.6.19,其中 9.6 是主要版本,19 是次要版本。
发布次要版本是不会改变内存的存储格式,因此总是和相同的主要版本兼容。例如,PostgreSQL 12.4 和 PostgreSQL 12.0 以及后续的 PostgreSQL 12.x 兼容。对于这些兼容版本的升级非常简单,只需要关闭数据库服务,安装替换二进制的可执行文件,重新启动服务即可。
接下来,我们主要讨论 PostgreSQL 的跨版本升级问题,例如从 PostgreSQL 12.x 升级到 PostgreSQL 13.y。主要版本的升级可能会修改内部数据的存储格式,因此需要执行额外的操作。常用的跨版本升级方法和适用场景如下:
升级方法
适用场景
停机时间
逻辑备份与还原
中小型数据库,例如小于 100 GB
支持跨平台数据迁移
取决于数据库的大小
pg_upgrade 工具
大中型数据库,例如大于 100 GB
本机就地升级
几分钟
逻辑复制
大中型数据库,例如大于 100 GB
跨平台支持
几秒钟
是的
"htmlcode">
pg_dumpall > outputfile如果已经安装了新版本的 PostgreSQL,可以使用新版本的 pg_dumpall 命令备份旧版本数据库。
停止旧版本的后台服务:
pg_ctl stop或者通过其他方式停止后台服务。
如果安装目录没有包含特定版本标识,可以将目录改名,必要时可以再修改回来。可以使用类似以下的命令重命名目录:
mv /usr/local/pgsql /usr/local/pgsql.old安装新版本 PostgreSQL 软件,假如安装目录仍然是 /usr/local/pgsql。
初始化一个新的数据库集群,需要使用数据库专用用户(通常是 postgres;如果是升级版本,应该已经存在该用户)执行操作:
/usr/local/pgsql/bin/initdb -D /usr/local/pgsql/data将旧版本配置文件 pg_hba.conf 和 postgresql.conf 等中的改动在对应的新配置文件中再次进行修改。
使用数据库专用用户启动新版本的后台服务:
/usr/local/pgsql/bin/postgres -D /usr/local/pgsql/data最后,利用新版本的 psql 命令还原数据:
/usr/local/pgsql/bin/psql -d postgres -f outputfile为了减少停机时间,可以将新版本的 PostgreSQL 安装到另一个目录(例如 /usr/local/pgsql-13),同时使用不同的端口启动服务。然后同时执行数据库的导出和导入:
pg_dumpall -p 5432 | psql -d postgres -p 5433执行以上操作时,新旧版本的后台服务同时运行,新版本使用 5433 端口,旧版本使用 5432 端口。
利用 pg_upgrade 工具进行升级
pg_upgrade 工具可以支持 PostgreSQL 跨版本的就地升级,不需要执行导出和导入操作。pg_upgrade 可以支持 PostgreSQL 8.4.X 到最新版本的升级,包括快照版本和测试版本。
pg_upgrade 提供了升级前的兼容性检查(-c 或者 --check 选项)功能, 可以发现插件、数据类型不兼容等问题。如果指定了 --link 选项,新版本服务可以直接使用原有的数据库文件而不需要执行复制,通常可以在几分钟内完成升级操作。
下面我们介绍这种升级方法的具体操作,假如当前 PostgreSQL 软件的安装目录位于 /usr/pgsql-12/,同时数据目录位于 /var/lib/pgsql/12/data/,我们将其升级为 PostgreSQL 13。
确定没有客户端访问之后备份数据库,然后停止旧版本的后台服务。例如 CentOS 可以执行以下命令:
sudo systemctl stop postgresql-12 sudo systemctl disable postgresql-12安装新版本的 PostgreSQL 软件。例如 PostgreSQL 13.0,安装目录位于 /usr/pgsql-13/。
初始化新版本的数据库集群。数据目录设置为 /var/lib/pgsql/13/data/。
如果旧版本中安装了扩展模块,在新版本中也需要安装相应的共享对象文件或者 DLL 文件。但是不要执行
CREATE EXTENSION
命令,因为会从旧数据库中进行升级。另外,如果使用了任何自定义的全文搜索文件(字典、同义词、词库、停用词),也需要复制到新的数据库集群目录中。停止新版本的后台服务。例如 CentOS 可以执行以下命令:
sudo systemctl stop postgresql-13通过 pg_upgrade 执行升级操作,使用数据库专用用户(通常是 postgres)执行以下操作:
/usr/pgsql-13/bin/pg_upgrade --old-datadir /var/lib/pgsql/12/data/ --new-datadir /var/lib/pgsql/13/data/ --old-bindir /usr/pgsql-12/bin/ --new-bindir /usr/pgsql-13/bin/ --check其中 --check 表示执行升级检查,而不会真的执行升级操作。通过检查之后,可以去掉该参数执行升级:
/usr/pgsql-13/bin/pg_upgrade --old-datadir /var/lib/pgsql/12/data/ --new-datadir /var/lib/pgsql/13/data/ --old-bindir /usr/pgsql-12/bin/ --new-bindir /usr/pgsql-13/bin/ --link其中 --link 表示将新版本的数据目录硬链接到旧版本的数据目录,而不会复制一份新的数据文件,可以快速进行升级。
将旧版本配置文件 pg_hba.conf 和 postgresql.conf 等中的改动在对应的新配置文件中再次进行修改。
启动新版本的后台服务。例如 CentOS 可以执行以下命令:
sudo systemctl start postgresql-13 sudo systemctl enable postgresql-13连接服务器查看数据库的版本信息:
SELECT version(); version | -------------------------------------------------------------------------------------------------------| PostgreSQL 13.0 on x86_64-pc-linux-gnu, compiled by gcc (GCC) 4.8.5 20150623 (Red Hat 4.8.5-39), 64-bit|收集统计信息。pg_upgrade 不会生成新版本数据库的统计信息,但是会创建一个脚本文件,执行该文件:
./analyze_new_cluster.sh如果确认升级成功,可以选择删除或者保留旧的数据库软件和集群。pg_upgrade 同样提供了一个删除旧数据库集群的脚本:
./delete_old_cluster.sh然后可以删除旧版本的 PostgreSQL 软件,例如 CentOS 可以执行以下命令:
yum remove postgresql12*如果想要回退到旧版本的数据库,可以分为不同的情况:
- 如果只运行了 --check 选项命令,表示没有真正执行升级,重新启动服务即可;
- 如果升级时没有使用 --link 选项,旧版本的数据库集群没有任何修改,重新启动服务即可;
- 如果升级时使用了 --link 选项,数据库文件可能已经被新版本的集群使用:
- 如果 pg_upgrade 在链接操作之前终止,旧版本的数据库集群没有任何修改,重新启动服务即可;
- 如果没有启动过新版本的后台服务,旧版本的数据库集群没有修改,但是链接过程已经将 $PGDATA/global/pg_control 文件重命名为 $PGDATA/global/pg_control.old;此时需要将该文件名中的 .old 后缀去掉,然后重新启动服务即可;
- 如果已经启动了新版本的数据库集群,已经修改了数据库文件,再启动旧版本的服务可能导致数据损坏;此时需要通过备份文件还原旧版本的数据库。
关于 pg_upgrade 的详细使用和升级注意事项,例如流复制结构和日志传输复制结构中备用节点的升级,可以参考官方文档。
使用逻辑复制功能进行升级
PostgreSQL 逻辑复制支持跨版本之间的数据复制,而且支持不同平台之间的复制,因此也可以用于实现版本升级。我们可以安装一个新版本的数据库作为复制的从节点,当数据已经同步时执行一次主从切换,然后关闭旧版本的主节点。主从切换的升级方法通常只需要几秒钟就能完成,利用第三方高可用组件甚至可以实现零停机时间升级。
PostgreSQL 10 开始提供了内置的逻辑复制功能,或者也可以使用 pglogical、Slony、Londiste 以及 Bucardo 等逻辑复杂工具。
关于 PostgreSQL 逻辑复制结构的创建和主从切换,可以参考官方文档。
总结
PostgreSQL 小版本升级只需要替换二进制文件即可,跨版本升级的方案主要有 3 种:通过 pg_dump/pg_dumpall 逻辑备份与还原进行升级,利用 pg_upgrade 工具进行升级,使用逻辑复制功能进行升级。了解它们的优缺点和适用场景可以帮助我们选择最佳的升级方式。