14.2 内核、发行版与托管服务
“基于 PostgreSQL”可能表示使用上游源码加少量补丁,也可能只表示接受一部分 PostgreSQL wire protocol。两者对扩展的意义完全不同。
选扩展前先冻结运行载体:
server implementation
+ server major/minor/build
+ OS/distribution/architecture
+ package source and build
+ topology and managed restrictions
+ database extension object version扩展不是脱离这些条件存在的功能标签。
14.2.1 上游 PostgreSQL、补丁内核与兼容性承诺
“内核”至少要说明源码与构建
在本书中,上游 PostgreSQL 指 PostgreSQL Global Development Group 发布的 代码与版本语义。供应者可以在其上:
- 回移安全或缺陷补丁;
- 增加认证、存储、优化器或复制能力;
- 替换某些系统组件;
- 发布自己的包名、构建号与支持周期;
- 形成需要独立升级路径的 fork。
“补丁少”不自动等于二进制兼容;“版本号相同”也不证明动态库来自相同 ABI 与编译选项。C 扩展会与 server headers、符号、内存上下文、catalog 和内部 API 交互。PostgreSQL 不承诺跨 major 的内部 C ABI,扩展通常必须按目标 major 构建。
先采原始身份:
SELECT version();
SHOW server_version;
SHOW server_version_num;
SELECT
name,
setting,
source
FROM pg_settings
WHERE name IN (
'server_version',
'server_version_num',
'data_directory',
'config_file',
'shared_preload_libraries'
);再采主机/包事实:
postgres --version
pg_config --version
pg_config --configure
uname -m在 Pigsty 环境还要记录 pg_version、pg_mode、镜像/仓库快照与节点实际包
清单。不要只复制应用连接返回的 version();代理、兼容层或读写路由可能让
它不足以唯一标识整个集群。
扩展兼容承诺要逐项问
对一个补丁内核或 fork,至少问:
| 问题 | 为什么影响扩展 |
|---|---|
| 是否使用上游系统目录布局 | 扩展 SQL 可能查询/修改 catalog |
| 是否支持 PGXS 与上游 server headers | 决定能否按目标内核构建 |
| 是否保持所需 C symbols/hook | 决定动态库能否加载和正确运行 |
| WAL、存储和复制是否改动 | 自定义类型/访问方法能否在备库恢复 |
pg_upgrade 是否使用上游路径 | 外部模块与数据格式怎样迁移 |
| 由谁发布扩展包 | 上游扩展 release 不等于目标内核构建 |
| 谁承担联合支持 | 内核供应者和扩展供应者是否互相认可组合 |
“这个扩展支持 PostgreSQL 18”只说明扩展项目的一个范围;目标若是 PostgreSQL 18 衍生内核,仍需该组合的构建与验证证据。
SQL 扩展也不必然可移植
没有 C 动态库只能降低 ABI 风险,不能消除语义耦合。纯 SQL 扩展可能依赖:
- 特定系统目录列;
- 特定函数、数据类型或语法版本;
- planner 行为;
- event trigger;
- trusted extension 机制;
- superuser/owner 权限;
- 复制、dump 或安全策略。
因此兼容性不是“C 扩展危险、SQL 扩展安全”的二分,而是依赖面的大小。
支持矩阵要精确到组合
不要写:
supports PostgreSQL而写:
server: upstream PostgreSQL 18.4, vendor build X
OS: Ubuntu 24.04 amd64
extension package: pgvector build Y
database object: vector 0.8.4
topology: 1 primary + 2 physical standbys
preload: not required
backup/restore: rehearsed on clean target Z同一扩展在 EL9/aarch64、Ubuntu/amd64 和某托管服务上是三个验证组合。
14.2.2 包仓库、容器镜像与托管白名单
包仓库解决供应,不替你做数据库升级
发行版包通常编码:
extension project version
PostgreSQL major
OS family/version
CPU architecture
vendor release/build例如 Pigsty 的包别名 pgvector 可以映射到不同系统上的:
EL: pgvector_18*
Debian: postgresql-18-pgvector这层映射很有价值,但别名不是 SQL 名:
pg_extensions: [pgvector] # package intent数据库中仍是:
CREATE EXTENSION vector; -- SQL extension name仓库有包只证明“某个源声明可以供应”;还要验证:
- 目标 OS/PG major/架构是否有具体 artifact;
- repo metadata、签名与校验是否可信;
- 包是否已经同步到本地/离线仓库;
- 所有节点安装的 build 是否相同;
- control、更新 SQL 和动态库是否都随包出现;
- 升级包后每个数据库的
extversion是否仍需迁移。
锁定生产变更时,保存具体包 NEVRA/DEB version 或文件哈希,不只保存一个 会随仓库漂移的“latest”别名。
容器把供应快照化,但不把数据生命周期一起快照
容器镜像可以把 server 与扩展文件打包在同一 digest 中:
image digest
├─ postgres binary
├─ control and SQL scripts
└─ shared libraries这有助于节点一致性,却有几个陷阱:
- 数据目录通常在持久卷,里面的
pg_extension.extversion不随镜像自动 更新; - 滚动换镜像期间,新旧 pod 可能同时服务,动态库 build 必须满足复制和 failover 条件;
- 恢复 job、备份验证 job 和临时维护容器也需要相同扩展文件;
- 镜像能启动不代表
ALTER EXTENSION UPDATE已完成; - 使用浮动 tag 会把可复现优势重新丢掉。
因此镜像 digest 是供应锁,不是数据库迁移状态。
托管白名单是产品合同
托管 PostgreSQL 常限制超级用户、文件系统和 server 参数。用户通常只能从 服务商允许列表中执行:
CREATE EXTENSION approved_name;这带来不同问题:
- 是否允许该扩展;
- 允许哪个对象版本;
- 哪些区域、实例规格或 PG major 可用;
- 是否需要服务商参数组/重启;
- 谁控制更新窗口;
- 是否暴露扩展 owner;
- 是否允许自定义 schema;
- 备份、只读副本、跨区恢复与 major upgrade 是否支持;
- 从服务迁出时怎样导出自定义类型数据。
托管服务显示“支持 pgvector”,仍不能直接套用自建包的版本、参数和升级 步骤。白名单名称相同,控制面合同可能不同。
仓库、镜像与白名单的共同锁文件
为每个环境维护:
server:
implementation: upstream-postgresql
version: 18.4
build: vendor-build-id
os: ubuntu-24.04-amd64
extension:
sql_name: vector
project: pgvector
package_alias: pgvector
package_version: exact-build
object_version: 0.8.4
preload: false
supply:
repo_snapshot_or_image_digest: immutable-id
control_sha256: ...
install_sql_sha256: ...
library_sha256: ...
validation:
primary: passed
standbys: passed
clean_restore: passed
major_upgrade_clone: passed不是所有项目都要手写 YAML,但这些字段必须能从 CMDB、inventory、镜像 SBOM、evidence 或变更单还原。
14.2.3 “兼容 PostgreSQL”需要逐层验证
五层兼容模型
把“兼容”拆为五层:
| 层 | 要验证什么 | 典型误判 |
|---|---|---|
| SQL 语义 | 类型、函数、事务、隔离、DDL 行为 | 能跑简单 CRUD 就等于 PostgreSQL |
| Wire protocol | 驱动连接、认证、参数、错误字段 | 驱动能连就等于 server 等价 |
| Catalog/API | pg_catalog、扩展机制、统计视图 | ORM 能用就等于管理工具能用 |
| Extension | control/SQL/C ABI、preload、成员与版本 | “支持 pgvector”就等于任意版本 |
| Operations | 备份、PITR、复制、failover、upgrade、监控 | 单实例功能测试代替生产生命周期 |
兼容声明必须说明通过了哪层。一个 wire-compatible 服务可能不提供
CREATE EXTENSION;一个支持扩展 SQL 接口的服务可能不允许用户控制版本;
一个上游二进制兼容内核仍可能在备份或升级控制面上有不同合同。
用需求驱动 probe
不要为了“全面”跑一堆无关 SQL。根据应用依赖形成最小 probe:
application contract
├─ exact type/function/operator signatures
├─ SQLSTATE and transaction behavior
├─ planner/index behavior
├─ privilege boundary
├─ backup/restore representation
└─ failover/upgrade behavior本章对 pg_trgm/vector 的 probe 包括:
-- 供应可见性
SELECT * FROM pg_available_extension_versions
WHERE name IN ('pg_trgm', 'vector');
-- 数据库对象
SELECT * FROM pg_extension
WHERE extname IN ('pg_trgm', 'vector');
-- 成员关系
SELECT ... FROM pg_depend WHERE deptype = 'e';
-- 索引实现
SELECT ... FROM pg_index JOIN pg_am JOIN pg_opclass ...;
-- 权限失败
ALTER EXTENSION pg_trgm UPDATE TO '1.6'; -- application: 42501
-- 行为与计划
EXPLAIN ... title % 'PostgreSQL extenson';
EXPLAIN ... ORDER BY embedding <-> '[1,0,0]';这些 probe 仍没有覆盖备库与恢复,所以 evidence 不能写“生产兼容已验证”。
区分等价、适配与迁移
三个词不要混用:
- 等价:在声明范围内行为相同;
- 适配:应用通过条件分支、兼容层或限制使用范围后可运行;
- 迁移:接受行为变化并修改 schema、查询、运维或 SLO。
例如目标不支持 HNSW,但支持精确向量距离:
不是:完全兼容 pgvector
可能是:类型/距离查询兼容,ANN 索引不兼容
决策是:小数据集适配,或迁移到另一检索架构精确描述可以阻止“兼容”在采购、开发和事故处理中不断膨胀。
兼容矩阵
对候选平台填表:
| 验证项 | 上游自建 | Pigsty L1 | 托管候选 | 证据 |
|---|---|---|---|---|
| SQL 扩展名/版本 | catalog | |||
| package/build | 服务商托管 | package/API | ||
| preload/restart | live setting | |||
| owner/权限 | negative test | |||
| GIN/HNSW | catalog + plan | |||
| 物理副本 | failover test | |||
| schema-only dump | dump artifact | |||
| clean restore | restore report | |||
| major upgrade | cloned rehearsal | |||
| portable export | row/checksum |
空格不是“默认通过”,而是未验证。若某项与业务无关,可以标 N/A 并说明
理由;不能把它悄悄留空后宣称全兼容。
停止线
遇到以下任一情况,不进入生产:
- 无法唯一标识 server/扩展 build;
- 主备节点供应状态不一致;
- 只有创建成功,没有 clean restore;
- 目标服务商不能说明 major upgrade 时怎样处理扩展;
- 自定义类型无法导出为稳定交换格式;
- 兼容层不返回应用依赖的 SQLSTATE/事务语义;
- 供应者与扩展项目相互否认联合支持;
- 只能使用浮动包/tag,无法复现已测组合。
本节结论
“PostgreSQL 兼容”不是布尔值,而是一个带版本、层次和证据的向量:
compatibility =
SQL × protocol × catalog × extension × operations
under exact version/build/topology constraints扩展越深入类型、索引、hook 与存储,越不能只验证前两层。
上一节:PostgreSQL 扩展机制 · 返回本章目录 · 下一节:扩展选型的六个问题 · 查看全书目录 · 查看索引中心