← 中文资源

简体中文版本

经过演练的 PostgreSQL 大版本升级

通过预演 pg_upgrade、验证备份和可回退的切换,将生产 PostgreSQL 集群升级到下一个大版本。

阅读英文原文

目标

把生产 PostgreSQL 从 16 升级到 17,尽量缩短停机时间。升级前必须确认扩展兼容、备份可恢复,并保留能够回到旧集群的路径,而不是只依赖一次成功的升级输出。

步骤

  1. 阅读发行说明,执行 SELECT extname FROM pg_extension; 列出扩展,确认每个扩展在目标版本都有可用包,并记录被删除或改名的参数。
  2. 在恢复出来的克隆库上预演,先用 --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
  1. 维护窗口开始前重新做一次基础备份,并在预演机验证能恢复;确认磁盘空间足够容纳完整副本和 WAL,通知应用方冻结写入。
  2. 停止写入和旧集群,去掉 --check 执行正式升级,启动 17 集群,并执行 vacuumdb --all --analyze-in-stages。
  3. 运行冒烟查询,对比关键表行数和执行计划,切换连接串后恢复写入。旧数据目录和旧二进制保留 14 天。

验证

pg_lsclusters 显示 17 在线、16 停止;关键表行数一致;应用冒烟测试通过;错误率在一小时内保持平稳;pg_upgrade 日志没有失败记录;扩展功能和复制槽均正常。

回滚

使用 --copy 时,停止新集群、启动旧集群并恢复原连接串即可回退;切换后写入新集群的数据会丢失,因此在验证通过前必须保持写入冻结。使用 --link 时旧集群已经无法启动,只能从基础备份恢复并重放 WAL,这是本流程中的不可逆步骤,只有在确认可以接受按备份恢复时才使用。14 天保留期内不要删除旧数据目录或旧二进制,也不要在保留期内执行清理脚本。