发展历史与版本演进
本节梳理 PostgreSQL 从伯克利校园项目到全球主流数据库的演进历程,并系统讲解版本号规则、发布节奏与支持周期。学完本节,你将能准确读懂"PostgreSQL 18.6"这样的版本号,并判断任一版本的支持状态。
前置知识
阅读本节前,建议先了解:PostgreSQL 是什么
基础概念
PostgreSQL 的历史可以分成三段,理解这三段是理解今天版本策略的前提:
| 阶段 | 时间 | 关键词 | 说明 |
|---|---|---|---|
| POSTGRES | 1986 ~ 1994 | 伯克利、学术研究 | 加州大学伯克利分校的科研项目,目标是解决当时关系数据库不支持复杂类型的问题 |
| Postgres95 | 1994 ~ 1996 | 加入 SQL、开源 | 学生 Andrew Yu 与 Jolly Chen 用 SQL 替换了原有的 QUEL 查询语言,并对外发布源码 |
| PostgreSQL | 1996 至今 | 更名、社区治理 | 更名后由全球开发者社区接管,进入每季度小版本、每年大版本的稳定节奏 |
几个必须掌握的术语:
- 主版本(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 的模式截然不同,下一节《版本选择建议》会专门展开。
语法与用法
查询当前数据库的版本信息,有三种粒度:
-- 1. 最详细:包含版本号、编译平台、编译器信息
SELECT version(); 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)-- 2. 结构化数字:适合在程序里做版本比较
SHOW server_version; -- 完整版本号,如 18.6
SHOW server_version_num; -- 数字形式,如 180006 server_version
----------------
18.6
(1 row)
server_version_num
--------------------
180006
(1 row)版本号的数字编码规则是 主版本 × 10000 + 次版本:
| 版本 | server_version | server_version_num | 计算方式 |
|---|---|---|---|
| PostgreSQL 16.15 | 16.15 | 160015 | 16×10000 + 15 |
| PostgreSQL 17.11 | 17.11 | 170011 | 17×10000 + 11 |
| PostgreSQL 18.0 | 18.0 | 180000 | 18×10000 + 0 |
| PostgreSQL 18.6 | 18.6 | 180006 | 18×10000 + 6 |
-- 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 里也可以直接取版本,便于自动化脚本判断:
# 只取版本号字符串
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.0 | 1997-01-29 | 更名 PostgreSQL 后的首个正式版 |
| 7.0 | 2000-05-08 | 引入 WAL,崩溃恢复能力大幅提升 |
| 7.4 | 2003-11-17 | 改进 IN/EXISTS 优化 |
| 8.0 | 2005-01-19 | 原生 Windows 支持 |
| 8.3 | 2008-02-04 | 堆仅元组(HOT)更新优化 |
| 9.0 | 2010-09-20 | 流复制(Streaming Replication)、热备(Hot Standby) |
| 9.1 | 2011-09-12 | 同步复制、可串行化快照隔离(SSI) |
| 9.2 | 2012-09-10 | JSON 类型、仅索引扫描(Index-Only Scan) |
| 9.3 | 2013-09-09 | 物化视图、LATERAL 连接 |
| 9.4 | 2014-12-18 | JSONB、逻辑解码 |
| 9.5 | 2016-01-07 | UPSERT(ON CONFLICT)、SKIP LOCKED、行级安全 |
| 9.6 | 2016-09-29 | 并行查询 |
| 10 | 2017-10-05 | 声明式分区、逻辑复制、SCRAM-SHA-256 |
| 11 | 2018-10-18 | JIT 编译、存储过程、INCLUDE 覆盖索引 |
| 12 | 2019-10-03 | 生成列、可插拔表访问方法、CTE 内联 |
| 13 | 2020-09-24 | 并行 VACUUM、增量排序、B-tree 去重 |
| 14 | 2021-09-30 | 管道模式、多范围类型、LZ4 压缩 |
| 15 | 2022-10-13 | MERGE、ICU 默认排序规则、JSON 日志格式 |
| 16 | 2023-09-14 | 逻辑复制支持备库、并行外连接、pg_stat_io |
| 17 | 2024-09-26 | JSON_TABLE、块级增量备份、流式 I/O |
| 18 | 2025-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 及以后):
18 . 6
│ │
│ └── 次要版本(Minor):安全修复与 bug 修复,可原地升级
└───────── 主版本(Major):新功能,升级需 pg_upgrade 或逻辑复制| 版本变化 | 类型 | 是否需 dump/restore | 是否需要重启 | 频率 |
|---|---|---|---|---|
| 18.5 → 18.6 | 次要版本升级 | 不需要 | 需要 | 每季度 |
| 18.6 → 19.0 | 主版本升级 | 需要(或 pg_upgrade) | 需要 | 每年 |
| 18.6 → 17.11 | 不支持降级 | — | — | — |
关键结论有三条:
- 次要版本升级是安全的。社区明确表示"执行次要版本升级比继续运行旧次要版本风险更低",因为修复的是已发现的问题。
- 主版本升级需要迁移工具。因为系统目录、存储格式、数据类型内部表示可能变化,数据目录不能直接兼容。
- 不支持跨主版本降级。18 的数据目录无法被 17 打开,回退只能靠备份或逻辑复制反向同步。
检查当前实例的小版本与可用更新:
# 查看已安装的 PostgreSQL 包版本(Debian/Ubuntu)
dpkg -l | grep postgresql
# 查看服务端二进制版本
/usr/lib/postgresql/18/bin/postgres --version
# Ubuntu/Debian 的 PostgreSQL 官方仓库提供了版本切换工具
pg_lsclustersVer 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 采用高度规律的年度发布周期,可以用一条时间轴概括:
┌──────────────────────────────────────────────────────────────┐
│ 一个典型的大版本周期(以 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) | 剩余支持 |
|---|---|---|---|---|---|
| 18 | 18.6 | ✅ | 2025-09-25 | 2030-11-14 | 约 4 年 |
| 17 | 17.11 | ✅ | 2024-09-26 | 2029-11-08 | 约 3 年 |
| 16 | 16.15 | ✅ | 2023-09-14 | 2028-11-09 | 约 2 年 |
| 15 | 15.19 | ✅ | 2022-10-13 | 2027-11-11 | 约 1 年 |
| 14 | 14.24 | ✅ | 2021-09-30 | 2026-11-12 | 不足 2 个月 |
| 13 | 13.23 | ❌ | 2020-09-24 | 2025-11-13 | 已 EOL |
| 12 | 12.22 | ❌ | 2019-10-03 | 2024-11-21 | 已 EOL |
| 11 | 11.22 | ❌ | 2018-10-18 | 2023-11-09 | 已 EOL |
| 10 | 10.23 | ❌ | 2017-10-05 | 2022-11-10 | 已 EOL |
| 9.6 | 9.6.24 | ❌ | 2016-09-29 | 2021-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) | 接近零 | 大库、要求不停机 | 订阅式实时同步,切换即用 |
# 路径 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 直接交换升级目录,避免复制/克隆/链接-- 路径 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 分钟以内。
# 第 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;" datname | size
-----------+---------
demo | 86 GB
postgres | 8553 kB
template1 | 8553 kB
(3 rows)决策:86 GB 属于中等规模。
- pg_dump/pg_restore 预计耗时 1~3 小时,停机太久 → 排除
- pg_upgrade --link 预计 5~20 分钟 → 可行,配合停写窗口
- 逻辑复制可做到接近零停机,但需要额外一套实例 → 备选
结论:选择 pg_upgrade --link,并在业务低峰期执行。# 第 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;" extname | extversion
----------+------------
plpgsql | 1.0
pg_trgm | 1.6
(2 rows)# 第 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=4Performing 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 版本一项重要的运维改进。
# 第 6 步:PostgreSQL 17 及更早版本才需要执行的重建统计(18 可直接跳过)
/usr/lib/postgresql/18/bin/vacuumdb --all --analyze-in-stages --jobs=4# 第 7 步:启动 18 集群并验证
pg_ctlcluster 18 main start
psql -h 127.0.0.1 -U postgres -d demo -tAc "SHOW server_version"
# 输出:18.6-- 第 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; product_rows | order_rows | index_count | extension_count
--------------+------------+-------------+-----------------
4 | 1 | 5 | 2
(1 row)-- 第 9 步:确认 14 已不再被需要后,卸载旧版本二进制
-- (--link 模式下旧数据目录已不可用,确认备份可恢复后再清理)
SELECT extname, extversion FROM pg_extension ORDER BY extname; 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 会直接报错。
-- 错误!用旧版本的 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.# 正确:始终使用目标版本目录下的工具
/usr/lib/postgresql/18/bin/pg_upgrade --old-datadir=... --new-datadir=...- 主版本升级无法回退。PostgreSQL 不支持降级数据目录。唯一的"回退"方式是恢复到升级前的备份,或者用逻辑复制把新库数据反向同步回旧库。因此升级前的备份不是可选项。
- EOL 后没有安全补丁。继续运行 EOL 版本意味着已知 CVE 暴露在公网,合规审计也会失败。
- 不要把
server_version_num的比较写死在代码里。扩展版本、编译参数不同都可能导致能力差异,功能探测(如查pg_catalog是否存在某函数)比版本号比较更可靠。
-- 不推荐:仅凭版本号猜测功能是否存在
-- 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 个。
下一节