跳至内容
30.2 三类大版本升级路径

30.2 三类大版本升级路径

大版本升级没有统一最优解。路径选择本质上是在四种成本之间交换:

业务不可写时间
额外计算/存储资源
变更系统数量与复杂度
回退与数据对账难度

先写约束,再选工具;不能因为团队最熟 pg_upgrade,就把所有数据库都压进一个停机 窗口。

30.2.1 pg_upgrade 与停机窗口

它升级 cluster,不是逐条重写业务数据

pg_upgrade 用新版本创建系统目录,再迁移旧 cluster 的 catalog 与用户 relation 文件, 因此通常比逻辑 dump/restore 快得多。它要求:

  • old/new server binaries 与 data/config directories 都可用;
  • compile-time 与 control-data 条件兼容;
  • 新 major 对应的扩展 shared libraries 已安装;
  • 两个 cluster 在正式 upgrade 时都停止;
  • 操作系统用户/数据库 install user、认证和 socket 可连接;
  • tablespace、standby、slot、统计与生成的 rebuild scripts 都有计划。

永远运行新版本pg_upgrade

/usr/lib/postgresql/18/bin/pg_upgrade \
  --old-bindir /usr/lib/postgresql/17/bin \
  --new-bindir /usr/lib/postgresql/18/bin \
  --old-datadir /pg/data/17 \
  --new-datadir /pg/data/18 \
  --username postgres \
  --socketdir /secure/short/socket \
  --check

--check 应在彩排和正式窗口前重复执行。若计划使用特定传输模式,检查时也要带相同 模式,才能覆盖文件系统约束。

文件传输模式决定速度和回退形态

模式空间/速度old cluster 可回退边界
default --copy需要完整副本,较慢old relation files 独立,新端启动后仍可启动旧端
--copy-file-range可能利用高效内核复制取决于实际文件系统行为,仍需实测
--cloneCoW 文件系统上快且省空间新旧逻辑独立,但要求文件系统支持
--link硬链接,最快且省空间新端一旦启动写共享文件,旧端不再安全
--swap可能更快,直接交换目录内容传输进入破坏阶段后旧端不再安全

不能把 --link 的分钟级结果与 --copy 的回退承诺同时写进 runbook。选择哪个模式, 就必须演练哪个模式、同一种文件系统、同样 tablespace 布局与数据规模。

本章为了验证“目标零写入时旧端可启动”,明确使用 --copy,禁止 link、clone、swap 和 --no-sync。升级完成后新 PG18 已启动并校验,随后停止新端、启动旧 PG17, 10,000 行 manifest 仍相等。这个结论只属于 copy 模式和本次 fixture。

停机窗口不只是一条命令的秒数

业务不可写窗口通常包含:

drain writers
  -> final checkpoint / backup evidence
      -> stop old topology
          -> pg_upgrade checks and transfer
              -> rebuild scripts / extension updates / collation work
                  -> staged ANALYZE
                      -> application validation
                          -> routing and pool drain

pg_upgrade 输出的 Upgrade Complete 只是中点。它会提示需运行的 rebuild/reindex 脚本;被这些脚本引用的表在完成前可能返回错误结果或性能极差。PostgreSQL 18 会迁移 大部分优化器统计,但 extended、扩展自定义和累计统计并不完整,仍建议:

vacuumdb --all --analyze-in-stages --missing-stats-only
vacuumdb --all --analyze-only

彩排要分别计时每一阶段,以生产数据克隆的 P95/P99 结果安排窗口,不能拿一个 10,000 行实验的 pg_upgrade 时间乘比例。

30.2.2 逻辑复制与渐进切换

逻辑复制把新 major 建成独立 cluster:

old source remains writable
  -> schema prepared on new target
      -> initial copy
          -> incremental apply
              -> shadow read and reconciliation
                  -> freeze, final marker, sequence sync
                      -> cutover

它的优点:

  • 业务不可写时间主要集中在最终冻结与切流;
  • 新旧环境可同时运行,便于真实应用影子验证;
  • 可以跨平台、改变物理布局、重配参数和扩展;
  • 目标可逐步扩容与预热。

代价已经在第 29 章验证:

  • DDL、sequence、large object 与许多对象不自动复制;
  • publication/subscription、replica identity、slot WAL 必须治理;
  • 目标写入会制造冲突或 silent drift;
  • 全量、增量、业务不变量和切流路由都需独立证据;
  • 回退在目标承接写入后需要 reverse sync 或 reconciliation。

跨 major 还要检查 row/column filter、generated columns、binary transfer 与协议选项在 两个版本交集中的语义。一般先升级 subscriber/target 能扩大兼容余量,但具体拓扑 需按官方 logical replication upgrade 章节执行。

PostgreSQL 17 起,pg_upgrade 可以在满足前提时迁移 logical slot/subscription 依赖;这不意味着任意逻辑复制拓扑能自动升级。publisher upgrade 前需要停用对应 subscription,循环、多节点和 two-phase 拓扑有非事务步骤,必须有备份和逐节点状态机。

Pigsty 推荐生产 major upgrade 优先考虑新建集群 + 逻辑迁移,因为它把应用验证和资源 准备移到切换前。这里的“推荐”仍需服从数据对象是否可逻辑复制、写入率、slot 容量、 DDL 频率和团队能否可靠完成对账。

30.2.3 dump/restore 与重建机会

dump/restore 是最“逻辑化”的升级:在新 cluster 按新版本规则重新创建对象和写入行。 它成本高,却也是一次摆脱历史物理包袱的机会:

  • 重排 tablespace、partition 与对象 owner;
  • 只迁移仍需保留的数据;
  • 统一 encoding/locale 的新建策略;
  • 重建全部 index,消除旧物理布局;
  • 审阅 schema、extension、privilege 和废弃对象;
  • 用 directory archive 并行 dump/restore。

常见路径:

# 用目标版本工具读取旧 server
pg_dump -Fd -j 8 -d app -f app.dump
pg_dumpall --globals-only > globals.sql

# 在新 server 恢复并审阅错误
psql -X -d postgres -f globals.sql
pg_restore -j 8 -d app_new app.dump

选择性恢复不是“完整 cluster 迁移”的同义词。需要另外处理:

roles and memberships
database-level settings
tablespaces
extensions and shared libraries
large objects
publications/subscriptions
security labels
replication slots
external files and FDW credentials

使用 target major 的 pg_dump,并读取 stderr 全部 warning。directory 格式是唯一支持 parallel dump 的 archive;custom/directory 都支持选择与重排 restore。并行增加 jobs + 1 个连接和源端负载,还可能因 DDL lock 排队而失败,必须在生产形态彩排。

dump/restore 的回退与逻辑迁移相似:旧端可继续保留,但目标开始承接独占写入后,改回 连接串仍会丢新事实。它不是因为“重建了一份”就天然可逆。

30.2.4 没有一种路径天然“滚动无感”

用约束选型

约束pg_upgradelogical replicationdump/restore
最小写停机较弱较弱
额外硬件可同机通常需要完整新集群通常需要完整新集群
升级速度通常最快取决于全量 + 追平通常最慢
真实影子验证有限最强恢复完成后可做
改物理布局有限最强
DDL/sequence 编排最复杂restore 负责大部分
旧端物理回退取决于 copy/link/swap切流前强切流前强
数据对账必需最重必需

一个常见组合不是三选一,而是:

production: logical replication
  + disaster rehearsal: dump/restore
  + small internal clusters: pg_upgrade

甚至同一项目会先用 dump/restore 生成测试克隆,再用 pg_upgrade 彩排正式路径。

“无感”要拆成多个 SLO

所谓无感至少包含:

connection establishment
read availability
write availability
transaction in flight
latency and plan stability
background jobs
CDC and replica continuity
error and retry semantics
data freshness

逻辑切换只有几秒写冻结,不代表旧池里的长事务、prepared statement、sequence、 缓存、ETL 与外部副作用无感。minor rolling 也会发生连接断开和 failover。pg_upgrade 即使文件迁移很快,post-upgrade reindex/ANALYZE 仍可能控制上线时间。

所以 runbook 不写“无感升级”,而写:

read_unavailable_budget: 5s
write_unavailable_budget: 30s
inflight_policy: drain-then-retry-idempotently
replication_rpo: 0
latency_gate: p99 <= baseline * 1.20
rollback_boundary: before first target-only commit

可测量的预算才是发布决策;“滚动”“在线”“秒级”只是实现特征。


上一节:先识别变化类型 · 返回本章目录 · 下一节:扩展与依赖升级 · 查看全书目录 · 查看索引中心

最后更新于