目标
把生产 PostgreSQL 从 16 升级到 17,尽量缩短停机时间。升级前必须确认扩展兼容、备份可恢复,并保留能够回到旧集群的路径,而不是只依赖一次成功的升级输出。
步骤
- 阅读发行说明,执行
SELECT extname FROM pg_extension;列出扩展,确认每个扩展在目标版本都有可用包,并记录被删除或改名的参数。 - 在恢复出来的克隆库上预演,先用
--check检查,再用--copy完整执行一次,记录耗时和错误:
/usr/lib/postgresql/17/bin/pg_upgrade \
--old-bindir=/usr/lib/postgresql/16/bin \
--new-bindir=/usr/lib/postgresql/17/bin \
--old-datadir=/var/lib/postgresql/16/main \
--new-datadir=/var/lib/postgresql/17/main \
--copy --check
- 维护窗口开始前重新做一次基础备份,并在预演机验证能恢复;确认磁盘空间足够容纳完整副本和 WAL,通知应用方冻结写入。
- 停止写入和旧集群,去掉
--check执行正式升级,启动 17 集群,并执行vacuumdb --all --analyze-in-stages。 - 运行冒烟查询,对比关键表行数和执行计划,切换连接串后恢复写入。旧数据目录和旧二进制保留 14 天。
验证
pg_lsclusters 显示 17 在线、16 停止;关键表行数一致;应用冒烟测试通过;错误率在一小时内保持平稳;pg_upgrade 日志没有失败记录;扩展功能和复制槽均正常。
回滚
使用 --copy 时,停止新集群、启动旧集群并恢复原连接串即可回退;切换后写入新集群的数据会丢失,因此在验证通过前必须保持写入冻结。使用 --link 时旧集群已经无法启动,只能从基础备份恢复并重放 WAL,这是本流程中的不可逆步骤,只有在确认可以接受按备份恢复时才使用。14 天保留期内不要删除旧数据目录或旧二进制,也不要在保留期内执行清理脚本。