Skip to content

发展历史与版本演进 ​

本节梳理 PostgreSQL 从伯克利校园项目到全球主流数据库的演进历程,并系统讲解版本号规则、发布节奏与支持周期。学完本节,你将能准确读懂"PostgreSQL 18.6"这样的版本号,并判断任一版本的支持状态。

前置知识

阅读本节前,建议先了解:PostgreSQL 是什么

基础概念 ​

PostgreSQL 的历史可以分成三段,理解这三段是理解今天版本策略的前提:

阶段时间关键词说明
POSTGRES1986 ~ 1994伯克利、学术研究加州大学伯克利分校的科研项目,目标是解决当时关系数据库不支持复杂类型的问题
Postgres951994 ~ 1996加入 SQL、开源学生 Andrew Yu 与 Jolly Chen 用 SQL 替换了原有的 QUEL 查询语言,并对外发布源码
PostgreSQL1996 至今更名、社区治理更名后由全球开发者社区接管,进入每季度小版本、每年大版本的稳定节奏

几个必须掌握的术语:

  • 主版本(Major Version):包含新功能的大版本,如 16、17、18。主版本升级不兼容数据目录,需要特殊处理。
  • 次要版本(Minor Version):只包含 bug 与安全修复的小版本,如 18.1、18.6。次要版本升级只需替换二进制文件并重启。
  • 支持周期(Support Lifecycle):官方提供修复的年限。PostgreSQL 的规则是主版本首发后 5 年。
  • 生命周期结束(EOL, End of Life):支持周期到期,之后不再有任何修复,包括安全漏洞。
  • 发布路线图(Roadmap):官方公布的下一批小版本计划日期。

有一个容易误解的点:PostgreSQL 没有"传统意义的 LTS 版本"。它不对某个版本做"长期支持"的特殊承诺,而是每个主版本都固定支持 5 年。因为每年发布一个新主版本,所以任何时刻通常都有 5 个左右的主版本处于支持状态。这一点与 Ubuntu LTS、Node.js LTS 的模式截然不同,下一节《版本选择建议》会专门展开。

语法与用法 ​

查询当前数据库的版本信息,有三种粒度:

sql
-- 1. 最详细:包含版本号、编译平台、编译器信息
SELECT version();
text
                                                 version
---------------------------------------------------------------------------------------------------------
 PostgreSQL 18.6 on x86_64-pc-linux-gnu, compiled by gcc (Debian 12.2.0-14) 12.2.0, 64-bit
(1 row)
sql
-- 2. 结构化数字:适合在程序里做版本比较
SHOW server_version;         -- 完整版本号,如 18.6
SHOW server_version_num;     -- 数字形式,如 180006
text
 server_version
----------------
 18.6
(1 row)

 server_version_num
--------------------
 180006
(1 row)

版本号的数字编码规则是 主版本 × 10000 + 次版本:

版本server_versionserver_version_num计算方式
PostgreSQL 16.1516.1516001516×10000 + 15
PostgreSQL 17.1117.1117001117×10000 + 11
PostgreSQL 18.018.018000018×10000 + 0
PostgreSQL 18.618.618000618×10000 + 6
sql
-- 3. 在应用/脚本里做版本门槛判断的常见写法
DO $$
BEGIN
  IF current_setting('server_version_num')::INT < 150000 THEN
    RAISE EXCEPTION '本脚本需要 PostgreSQL 15 及以上版本';
  END IF;
  RAISE NOTICE '版本检查通过:%', current_setting('server_version');
END
$$;

在 shell 里也可以直接取版本,便于自动化脚本判断:

bash
# 只取版本号字符串
psql -h 127.0.0.1 -U postgres -d demo -tAc "SHOW server_version"
# 输出:18.6

# 只取数字版本号,便于数值比较
psql -h 127.0.0.1 -U postgres -d demo -tAc "SHOW server_version_num"
# 输出:180006

详细说明 ​

从 POSTGRES 到 PostgreSQL ​

1986 年,加州大学伯克利分校的 Michael Stonebraker 教授启动了 POSTGRES 项目(名字是 "post-Ingres" 的双关,Ingres 是他此前的另一个数据库项目)。当时商业关系数据库已能处理数字与字符串,但对几何、时间、自定义类型支持很差。POSTGRES 的设计目标正是可扩展的类型系统——这一基因延续至今,成为 PostgreSQL "什么都能装" 的根源。

1994 年,Andrew Yu 与 Jolly Chen 将查询语言从 QUEL 换成 SQL,产物称为 Postgres95,并以开源方式发布。1996 年,项目正式更名为 PostgreSQL,并移交社区治理,采取了不归属于任何公司的开发模式——这也是它至今保持中立、不被单一厂商控制的原因。官方对这段历史的表述是"over 35 years of active development"(超过 35 年的持续开发)。

各主要版本的发布时间 ​

下表列出仍被广泛使用或具有里程碑意义的版本(时间以官方版本策略页为准):

主版本首次发布里程碑特性
6.01997-01-29更名 PostgreSQL 后的首个正式版
7.02000-05-08引入 WAL,崩溃恢复能力大幅提升
7.42003-11-17改进 IN/EXISTS 优化
8.02005-01-19原生 Windows 支持
8.32008-02-04堆仅元组(HOT)更新优化
9.02010-09-20流复制(Streaming Replication)、热备(Hot Standby)
9.12011-09-12同步复制、可串行化快照隔离(SSI)
9.22012-09-10JSON 类型、仅索引扫描(Index-Only Scan)
9.32013-09-09物化视图、LATERAL 连接
9.42014-12-18JSONB、逻辑解码
9.52016-01-07UPSERT(ON CONFLICT)、SKIP LOCKED、行级安全
9.62016-09-29并行查询
102017-10-05声明式分区、逻辑复制、SCRAM-SHA-256
112018-10-18JIT 编译、存储过程、INCLUDE 覆盖索引
122019-10-03生成列、可插拔表访问方法、CTE 内联
132020-09-24并行 VACUUM、增量排序、B-tree 去重
142021-09-30管道模式、多范围类型、LZ4 压缩
152022-10-13MERGE、ICU 默认排序规则、JSON 日志格式
162023-09-14逻辑复制支持备库、并行外连接、pg_stat_io
172024-09-26JSON_TABLE、块级增量备份、流式 I/O
182025-09-25异步 I/O、跳跃扫描(Skip Scan)、uuidv7()、虚拟生成列

值得注意的是 9.x 到 10 的断代:在 PostgreSQL 10 之前,大版本号是"前两段"(9.4 → 9.5 → 9.6),从 10 开始改为"第一段"(10 → 11 → 12)。这解释了为什么版本时间表里 9.6 之后直接跳到 10——本质上 9.6 的后继就是 10,只是命名方式变了。

版本号的含义 ​

完整的版本号规则如下(适用于 PostgreSQL 10 及以后):

text
       18  .  6
       │      │
       │      └── 次要版本(Minor):安全修复与 bug 修复,可原地升级
       └───────── 主版本(Major):新功能,升级需 pg_upgrade 或逻辑复制
版本变化类型是否需 dump/restore是否需要重启频率
18.5 → 18.6次要版本升级不需要需要每季度
18.6 → 19.0主版本升级需要(或 pg_upgrade)需要每年
18.6 → 17.11不支持降级———

关键结论有三条:

  1. 次要版本升级是安全的。社区明确表示"执行次要版本升级比继续运行旧次要版本风险更低",因为修复的是已发现的问题。
  2. 主版本升级需要迁移工具。因为系统目录、存储格式、数据类型内部表示可能变化,数据目录不能直接兼容。
  3. 不支持跨主版本降级。18 的数据目录无法被 17 打开,回退只能靠备份或逻辑复制反向同步。

检查当前实例的小版本与可用更新:

bash
# 查看已安装的 PostgreSQL 包版本(Debian/Ubuntu)
dpkg -l | grep postgresql

# 查看服务端二进制版本
/usr/lib/postgresql/18/bin/postgres --version

# Ubuntu/Debian 的 PostgreSQL 官方仓库提供了版本切换工具
pg_lsclusters
text
Ver Cluster Port Status Owner    Data directory              Log file
18  main    5432 online postgres /var/lib/postgresql/18/main  /var/log/postgresql/postgresql-18-main.log
17  main    5433 online postgres /var/lib/postgresql/17/main  /var/log/postgresql/postgresql-17-main.log

每年一个大版本的发布节奏 ​

PostgreSQL 采用高度规律的年度发布周期,可以用一条时间轴概括:

text
┌──────────────────────────────────────────────────────────────┐
│  一个典型的大版本周期(以 PostgreSQL 18 为例)                │
├──────────────────────────────────────────────────────────────┤
│                                                              │
│  2024-07   18 的分支从 master 切出,进入开发冻结              │
│  2024-10   18 Beta 1 发布                                    │
│  2025-01 ~ 2025-05   Beta 2 / Beta 3 / RC 1(多轮测试)      │
│  2025-05   特性冻结(Feature Freeze)                         │
│  2025-09-25   18.0 正式发布(GA)                             │
│  2025-11   18.1(首次小版本)                                 │
│  2026-02   18.2                                              │
│  2026-05   18.3                                              │
│  2026-08   18.4 / 18.5 / 18.6(每季度一次)                   │
│  ……                                                          │
│  2030-11-14   18 的最终小版本,之后 EOL                       │
│                                                              │
└──────────────────────────────────────────────────────────────┘

注意几个细节:

  • 每个主版本都遵循同样的节奏,因此每年 9~10 月会有一次"大版本发布 + 所有受支持版本的小版本发布"。
  • 小版本每季度一次(约 2 月、5 月、8 月、11 月)。若出现紧急安全漏洞,会额外发布。
  • Beta 期间会有多次迭代。以 2026 年的 PostgreSQL 19 为例,截至 8 月已发布到 Beta 3,与 18.6、17.11、16.15、15.19、14.24 这批小版本同日发布——这体现了"大版本与小版本同节奏"的规律。
  • 生产环境不要追 Beta/RC,等待正式版(GA)后再评估。

支持周期与维护时间表 ​

官方规则:主版本自首次发布起支持 5 年,到期发布最后一个次要版本后进入 EOL。截至 2026 年 9 月,官方维护时间表如下:

版本当前次要版本支持中首次发布最终发布(EOL)剩余支持
1818.6✅2025-09-252030-11-14约 4 年
1717.11✅2024-09-262029-11-08约 3 年
1616.15✅2023-09-142028-11-09约 2 年
1515.19✅2022-10-132027-11-11约 1 年
1414.24✅2021-09-302026-11-12不足 2 个月
1313.23❌2020-09-242025-11-13已 EOL
1212.22❌2019-10-032024-11-21已 EOL
1111.22❌2018-10-182023-11-09已 EOL
1010.23❌2017-10-052022-11-10已 EOL
9.69.6.24❌2016-09-292021-11-11已 EOL

从表中能读出三个实用信息:

  • 14 处于 EOL 倒计时。官方已发出提醒,建议运行 14 的生产环境尽快规划升级。
  • 任一时刻约有 5 个主版本受支持(当前是 14~18)。这就是"没有 LTS"的具体体现:你不需要等某个"长期支持版",只要选一个还有 3 年以上支持期的主版本即可。
  • 升级窗口应留足时间。一个主版本从 GA 到手头项目升级,通常需要 1~2 年。因此更稳妥的策略是:始终比 EOL 提前至少 1 年完成升级。

升级路径概览 ​

主版本升级有三条路径,细节将在后续章节展开,这里先建立整体认知:

路径停机时间适用规模原理
pg_dump / pg_restore长(小时级)小库(< 几十 GB)逻辑导出 SQL,再导入新库
pg_upgrade短(分钟级)中大库复用数据文件,仅重建系统目录
逻辑复制(Logical Replication)接近零大库、要求不停机订阅式实时同步,切换即用
bash
# 路径 1:pg_dump / pg_restore(适合小库,可跨平台跨大版本)
pg_dump -h 127.0.0.1 -U postgres -d demo -Fc -f /backup/demo.dump
createdb -h 127.0.0.1 -U postgres demo_new
pg_restore -h 127.0.0.1 -U postgres -d demo_new -j 4 /backup/demo.dump

# 路径 2:pg_upgrade(就地升级,速度快)
# --link 用硬链接代替复制,最省空间与时间,但升级后旧集群不可用
/usr/lib/postgresql/18/bin/pg_upgrade \
  --old-datadir=/var/lib/postgresql/17/main \
  --new-datadir=/var/lib/postgresql/18/main \
  --old-bindir=/usr/lib/postgresql/17/bin \
  --new-bindir=/usr/lib/postgresql/18/bin \
  --link --jobs=4

# PostgreSQL 18+:pg_upgrade 会保留规划器统计信息,升级后无需等待 ANALYZE 重建
# PostgreSQL 18+:支持 --swap 直接交换升级目录,避免复制/克隆/链接
sql
-- 路径 3:逻辑复制(不停机迁移的核心思路)
-- 在旧库(发布端)执行:
CREATE PUBLICATION pub_demo FOR ALL TABLES;

-- 在新库(订阅端)执行:
CREATE SUBSCRIPTION sub_demo
  CONNECTION 'host=old-host port=5432 dbname=demo user=repl password=***'
  PUBLICATION pub_demo;
-- 待数据追平后,停止写入旧库并切换应用到新库

版本兼容性约束

逻辑复制只能从低版本同步到高版本(如 17 → 18),不能反向。跨多个主版本(如 14 → 18)是允许的,但必须仔细阅读中间每个版本的升级说明。

实战示例 ​

场景:一个正在运行 PostgreSQL 14 的生产库,需要在 EOL(2026-11-12)前升级到 18,并且要求停机时间控制在 10 分钟以内。

bash
# 第 1 步:确认当前环境状态
psql -h 127.0.0.1 -U postgres -d demo -tAc "SHOW server_version"
# 输出:14.24

# 查看数据库总大小,判断选哪条升级路径
psql -h 127.0.0.1 -U postgres -d demo -c "
  SELECT datname,
         pg_size_pretty(pg_database_size(datname)) AS size
  FROM pg_database
  ORDER BY pg_database_size(datname) DESC;"
text
  datname  |  size
-----------+---------
 demo      | 86 GB
 postgres  | 8553 kB
 template1 | 8553 kB
(3 rows)
text
决策:86 GB 属于中等规模。
  - pg_dump/pg_restore 预计耗时 1~3 小时,停机太久 → 排除
  - pg_upgrade --link 预计 5~20 分钟 → 可行,配合停写窗口
  - 逻辑复制可做到接近零停机,但需要额外一套实例 → 备选
结论:选择 pg_upgrade --link,并在业务低峰期执行。
bash
# 第 2 步:升级前检查清单
# 2.1 确认是两个独立的安装版本并存(不能相互覆盖)
ls -d /usr/lib/postgresql/*/bin/ | sort
# /usr/lib/postgresql/14/bin/
# /usr/lib/postgresql/18/bin/

# 2.2 备份关键配置与角色(pg_upgrade 不迁移这些)
cp /etc/postgresql/14/main/postgresql.conf /backup/pg14-postgresql.conf
cp /etc/postgresql/14/main/pg_hba.conf     /backup/pg14-pg_hba.conf
pg_dumpall -h 127.0.0.1 -U postgres --globals-only -f /backup/pg14-globals.sql

# 2.3 全量物理备份(兜底,必须做)
pg_basebackup -h 127.0.0.1 -U replicator -D /backup/base14 -Ft -z -P

# 2.4 检查扩展兼容性(14 装的扩展必须在 18 上可用)
psql -h 127.0.0.1 -U postgres -d demo -c "
  SELECT extname, extversion FROM pg_extension ORDER BY extname;"
text
 extname  | extversion
----------+------------
 plpgsql  | 1.0
 pg_trgm  | 1.6
(2 rows)
bash
# 第 3 步:初始化 18 的新集群
/usr/lib/postgresql/18/bin/initdb -D /var/lib/postgresql/18/main \
  --encoding=UTF8 --locale=C.UTF-8 --data-checksums

# 第 4 步:停掉两个集群,确保升级期间无写入
pg_ctlcluster 14 main stop
pg_ctlcluster 18 main stop

# 第 5 步:执行升级(--link 秒级移动数据文件,--jobs 并行检查)
/usr/lib/postgresql/18/bin/pg_upgrade \
  --old-datadir=/var/lib/postgresql/14/main \
  --new-datadir=/var/lib/postgresql/18/main \
  --old-bindir=/usr/lib/postgresql/14/bin \
  --new-bindir=/usr/lib/postgresql/18/bin \
  --link --jobs=4 --check

# 检查通过后去掉 --check 真正执行
/usr/lib/postgresql/18/bin/pg_upgrade \
  --old-datadir=/var/lib/postgresql/14/main \
  --new-datadir=/var/lib/postgresql/18/main \
  --old-bindir=/usr/lib/postgresql/14/bin \
  --new-bindir=/usr/lib/postgresql/18/bin \
  --link --jobs=4
text
Performing Consistency Checks on Old Live Server
------------------------------------------------
Checking cluster versions                                   ok
Checking database user is the install user                   ok
Checking database connection settings                        ok
Checking for prepared transactions                           ok

Upgrade Complete
----------------
Optimizer statistics are not transferred by pg_upgrade.

注意上面这行提示:在 PostgreSQL 18 之前,规划器统计信息不会被 pg_upgrade 迁移,升级后必须立刻 ANALYZE,否则查询性能会明显下降。PostgreSQL 18 起,统计信息会随升级保留,这是 18 版本一项重要的运维改进。

bash
# 第 6 步:PostgreSQL 17 及更早版本才需要执行的重建统计(18 可直接跳过)
/usr/lib/postgresql/18/bin/vacuumdb --all --analyze-in-stages --jobs=4
bash
# 第 7 步:启动 18 集群并验证
pg_ctlcluster 18 main start

psql -h 127.0.0.1 -U postgres -d demo -tAc "SHOW server_version"
# 输出:18.6
sql
-- 第 8 步:业务层面验证 —— 数据行数、关键索引、扩展是否都完好
SELECT
  (SELECT count(*) FROM products) AS product_rows,
  (SELECT count(*) FROM orders)   AS order_rows,
  (SELECT count(*) FROM pg_indexes WHERE schemaname = 'public') AS index_count,
  (SELECT count(*) FROM pg_extension) AS extension_count;
text
 product_rows | order_rows | index_count | extension_count
--------------+------------+-------------+-----------------
           4 |          1 |           5 |               2
(1 row)
sql
-- 第 9 步:确认 14 已不再被需要后,卸载旧版本二进制
-- (--link 模式下旧数据目录已不可用,确认备份可恢复后再清理)
SELECT extname, extversion FROM pg_extension ORDER BY extname;
text
 extname  | extversion
----------+------------
 pg_trgm  | 1.6
 plpgsql  | 1.0
(2 rows)

注意事项 ​

  • "PostgreSQL 有 LTS 版本"是错误认知。官方不做 LTS 区分,所有主版本一律 5 年支持期。选版本看的是"剩余支持年限",不是版本号本身。
  • pg_upgrade 不会迁移非数据文件。postgresql.conf、pg_hba.conf、.pgpass 等配置必须手工对比迁移,否则会出现"升级成功但连不上/参数丢失"的问题。
  • --link 模式有不可逆风险。它以硬链接替代复制,升级后旧集群立即不可用,失去回退能力。生产环境务必先做 pg_basebackup。
  • 不要跨版本混用客户端与服务端二进制。用 14 的 psql 连 18 通常可行,但用 14 的 pg_upgrade 去升级 18 会直接报错。
text
-- 错误!用旧版本的 pg_upgrade 升级新集群
/usr/lib/postgresql/14/bin/pg_upgrade --old-datadir=... --new-datadir=...
-- 报错:This utility must be run from the version of PostgreSQL you are upgrading TO.
bash
# 正确:始终使用目标版本目录下的工具
/usr/lib/postgresql/18/bin/pg_upgrade --old-datadir=... --new-datadir=...
  • 主版本升级无法回退。PostgreSQL 不支持降级数据目录。唯一的"回退"方式是恢复到升级前的备份,或者用逻辑复制把新库数据反向同步回旧库。因此升级前的备份不是可选项。
  • EOL 后没有安全补丁。继续运行 EOL 版本意味着已知 CVE 暴露在公网,合规审计也会失败。
  • 不要把 server_version_num 的比较写死在代码里。扩展版本、编译参数不同都可能导致能力差异,功能探测(如查 pg_catalog 是否存在某函数)比版本号比较更可靠。
sql
-- 不推荐:仅凭版本号猜测功能是否存在
-- IF server_version_num >= 170000 THEN 使用 json_table(...)

-- 推荐:直接探测函数是否可用
SELECT EXISTS (
  SELECT 1 FROM pg_proc p
  JOIN pg_namespace n ON n.oid = p.pronamespace
  WHERE p.proname = 'json_table'
) AS has_json_table;
  • 升级后不要立刻删除旧集群。保留至少一个完整的业务周期(如 1~2 周),确认无异常后再清理,否则问题暴露时无从对比。

最佳实践 ​

  • 把"距离 EOL 不足 1 年"作为强制升级信号,纳入运维日历与季度巡检清单。
  • 每年至少做一次次要版本升级,跟随官方季度发布节奏,不要攒到 EOL 前集中升级。
  • 主版本升级必须先在预发环境完整演练,包括 pg_upgrade --check、统计信息重建、扩展兼容性验证。
  • 生产升级首选逻辑复制或 pg_upgrade,避免 pg_dump/pg_restore 造成的长时间停机。
  • 升级前用 pg_upgrade --check 做预检,它会在不修改数据的前提下报告不兼容项。
  • 配置文件纳入版本管理(如 Ansible / Git),升级时直接套用新模板 + 差异对比,而不是手工搬运。
  • 关注官方 Versioning Policy 页面,以它作为 EOL 日期的唯一权威来源,不要依赖二手资料。
  • 在多实例环境中统一版本。混合版本会增加驱动兼容、SQL 行为差异与运维复杂度,建议把主版本收敛到 1~2 个。

下一节

继续学习:PostgreSQL vs MySQL vs Oracle

参考链接 ​