跳至内容
14.2 内核、发行版与托管服务

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_versionpg_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

这有助于节点一致性,却有几个陷阱:

  1. 数据目录通常在持久卷,里面的 pg_extension.extversion 不随镜像自动 更新;
  2. 滚动换镜像期间,新旧 pod 可能同时服务,动态库 build 必须满足复制和 failover 条件;
  3. 恢复 job、备份验证 job 和临时维护容器也需要相同扩展文件;
  4. 镜像能启动不代表 ALTER EXTENSION UPDATE 已完成;
  5. 使用浮动 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/APIpg_catalog、扩展机制、统计视图ORM 能用就等于管理工具能用
Extensioncontrol/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/restartlive setting
owner/权限negative test
GIN/HNSWcatalog + plan
物理副本failover test
schema-only dumpdump artifact
clean restorerestore report
major upgradecloned rehearsal
portable exportrow/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 扩展机制 · 返回本章目录 · 下一节:扩展选型的六个问题 · 查看全书目录 · 查看索引中心

最后更新于