14.4 生命周期与升级耦合
扩展有两条相互耦合、却不会自动同步的生命周期:
运维事故往往发生在两条线暂时分离时:包已升级而对象未升级、对象已写入 catalog 而新备库缺库、备份完整却恢复环境没有旧脚本。
14.4.1 安装版本不等于数据库对象版本
三个“版本”不要合成一个字段
至少记录:
| 名称 | 来源 | 示例 |
|---|---|---|
| 项目/release 版本 | upstream release/package metadata | pgvector 0.8.4 |
| 节点软件包 build | rpm/deb/image | vendor release + PG18 + OS |
| 数据库对象版本 | pg_extension.extversion |
vector 0.8.4 |
有些包一次提供多个 SQL 对象版本和更新脚本。于是:
两者不同并不必然错误,但必须是被管理的过渡状态。
先装包,再逐库迁移
一个安全的普通更新顺序:
为什么先把文件铺到所有节点?因为 failover 不应把一个刚完成对象更新的
数据库交给缺动态库的备库。物理复制会复制数据目录变化,不会替你把
$libdir 文件复制到另一台主机。
为什么逐库?扩展是 database-scoped。一个 cluster 中:
列出的每个数据库都有自己的 pg_extension;postgres 已经 1.6,不代表
app、analytics 或 template 也已经 1.6。
建立跨节点、跨数据库矩阵
节点侧:
数据库侧:
聚合后应能回答:
只保存 \dx 截图无法发现某台备库缺包,也无法显示其他数据库。
control 默认版本不会升级已有对象
升级包后:
可能显示:
含义是:
- 新执行
CREATE EXTENSION pg_trgm默认创建 1.6; - 当前数据库对象仍是 1.3;
- 只有显式
ALTER EXTENSION ... UPDATE才迁移它。
不要靠重跑:
期待升级。IF NOT EXISTS 只会 notice 并保留现有对象,也不保证同名现有
对象就是期望内容。
更新前读脚本,不只读 release notes
查看路径:
再读取实际 package 中:
评审:
- 是否改类型或存储格式;
- 是否重建/重写索引;
- 是否触碰扩展配置表;
- 是否删除/重命名函数与操作符;
- 是否会扫描业务数据;
- 需要何种锁;
- 失败是否能事务回滚;
- 更新后的旧应用是否仍兼容。
本章对这些文件和动态库做 SHA-256,保证复验时读的是同一构建;哈希不替代 代码评审。
package rollback 不等于 object rollback
假设已经把对象从 1.3 更新到 1.6,再把 OS 包降回只支持 1.3:
这是更危险的不一致。反向对象迁移只有在扩展明确提供 downgrade path 且 数据格式兼容时才可能。更常见的回退是:
- 在更新前保留可恢复备份/快照;
- 在 clone 上验证;
- 更新后向前修复;
- 若必须回退,恢复到更新前一致时间点并协调业务数据。
因此扩展更新的“可回滚”不能只写 apt downgrade。
14.4.2 大版本升级、备份恢复与逻辑复制兼容
pg_upgrade 不会替你验证外部模块
PostgreSQL 官方 pg_upgrade
文档明确提醒:所有外部模块必须与新 server 二进制兼容;pg_upgrade
无法检查这一点。新集群主库与备库都要安装匹配 shared libraries。
大版本升级前,对每个扩展冻结:
可能的顺序取决于扩展:
也可能要求另一个顺序。以扩展的目标版本升级文档为准。
pg_upgrade --check 通过不等于扩展可用。clone rehearsal 至少要:
- 启动新集群;
- 查询每个扩展类型/函数;
- 检查 expression index/opclass;
- 重建或验证要求重建的索引;
- 跑应用回归;
- 启动新备库;
- 验证 dump/restore 和监控。
物理备份包含数据,不包含 OS 供应链
物理备份复制数据库文件和 WAL。它不会自动保存:
- PostgreSQL server binary;
- control 与版本 SQL;
- 动态库;
- preload 配置的外部部署来源;
- OS package repository。
恢复手册必须能重建:
只保留最新仓库,未必能恢复三年前依赖旧扩展对象版本的备份。长期保留策略要 考虑 package snapshot、image digest 或可复现构建。
逻辑 dump 用声明恢复扩展
PostgreSQL 把扩展视为整体。全库 schema-only dump 中,本章看到:
却没有:
这正是扩展机制的 dump 合同。恢复顺序隐含要求:
本章还证明一个容易忽略的选择性 dump 语义:
输出包含:
但不包含 CREATE EXTENSION。PostgreSQL pg_dump 文档对 --schema
选择明确警告:它不保证自动带上所选对象依赖的所有对象。这个 artifact
不能单独在洁净环境恢复,必须由恢复清单显式先创建扩展。
参见 pg_dump。
clean restore 是唯一有力的恢复证据
不要在原集群上执行 dump 后立刻宣称可恢复。洁净环境要求:
- 没有预装数据库扩展对象;
- 使用冻结 server/package build;
- 从空 database 开始;
- 按 runbook 恢复;
- 验证 extension owner/schema/version/member;
- 验证业务行数/checksum;
- 验证查询、计划与权限;
- 记录时间、日志和失败。
若恢复必须“手工试几个版本直到成功”,供应合同尚未完成。
逻辑复制不复制 schema 与扩展生命周期
内置逻辑复制主要复制表数据变更,不替你复制 DDL、extension control files
或 CREATE EXTENSION。发布端列使用自定义类型时,订阅端必须预先拥有可
接受该列值、函数和索引的兼容 schema。
评审:
- publisher/subscriber 类型名与语义;
- text/binary 传输与转换能力;
- extension object version;
- DDL 发布顺序;
- replica identity;
- extension-owned 配置/metadata 是否作为普通表复制;
- 订阅端触发器/默认值/约束的执行差异;
- major/architecture 组合。
“两端都显示 extension installed”仍不足以证明版本/数据语义兼容。
如果逻辑复制被用作迁移出口,先把自定义数据转换为内置交换类型通常更容易
控制。例如本章把 vector(3) 显式转为 text,而不是要求目标立即加载
同一 extension。
参见 Logical Replication Restrictions。
备库与 failover
物理 standby 会重放创建表、类型依赖和 extension catalog 变化,但不会 运行节点包管理器。变更前:
检查不能只 SSH 到主库。新加入节点、灾备节点、延迟副本和备份 restore worker 都属于供应范围。
14.4.3 依赖扩展不可用时的降级策略
先区分必需能力与增强能力
扩展依赖可分:
| 类型 | 例子 | 不可用时 |
|---|---|---|
| 数据可读必需 | 业务列是自定义类型 | 数据库/查询可能无法正常使用 |
| 写入必需 | trigger/function 是写入合同 | 应停止写而不是绕过不变量 |
| 查询增强 | 可重建索引/opclass | 可回退较慢原生查询 |
| 观测增强 | 统计/采样扩展 | 核心业务可运行,诊断能力下降 |
| 维护增强 | repack/调度工具 | 延后维护并告警 |
只有后两三类适合真正“降级”。把自定义列类型说成可选能力是自欺。
设计能力探测,但不要每次请求查 catalog
发布/启动时探测:
再验证所需签名与索引:
结果进入部署 gate 或低基数健康状态,而不是每个请求动态猜。应用 feature flag 必须与数据库迁移阶段同步:
可重建索引的降级
pg_trgm 例子:
降级查询语义不同,API 要明确:
- 是否返回较少结果;
- 是否暂停 fuzzy mode;
- 延迟是否提高;
- 哪些 SLO 暂时失效。
不要悄悄返回不同业务含义。
自定义类型的退场顺序
以 vector 为例:
依赖检查:
绝不以:
作为“清理方便”的生产脚本。CASCADE 会把尚未迁走的业务对象一起删除。
当动态库临时缺失
若 catalog 已有扩展而节点缺 library:
- 不要继续 failover 到该节点;
- 阻断相关流量或节点晋升;
- 从受控仓库恢复匹配包;
- 验证哈希、loadability 与查询;
- 检查所有其他节点是否同样漂移;
- 解释配置管理为何未发现;
- 完成恢复/备库回归。
删除 catalog 中 extension 不是修动态库缺失的第一反应,尤其当业务类型依赖 它时。
降级 SLO
ADR 预先定义:
没有时间、语义和 owner 的 fallback 只是愿望。
本节结论
扩展生命周期的真正完成条件:
CREATE EXTENSION 只完成第一项的一部分。
上一节:扩展选型的六个问题 · 返回本章目录 · 下一节:用 Pigsty 管理扩展可用性 · 查看全书目录 · 查看索引中心