前言
PostgreSQL 19 Beta 1 在 2026 年 6 月 4 日发布,正式版(GA)预计 9-10 月落地。与往年"追新特性"不同,这个版本的 200 多项变更里,真正值得关注的几乎全是运维和性能层面:autovacuum 终于支持并行了、内置了 REPACK 在线重建表、外键插入性能翻倍、WAIT FOR LSN 解决了读写分离的"读到旧数据"问题。
但同样重要的是几个默认值变更------JIT 默认关闭、RADIUS 认证直接移除、TOAST 压缩默认换成 lz4------如果你的生产环境不做提前验证,升级时很可能踩坑。
这篇文章不罗列全部 200 项变更,而是站在后端工程师和 DBA 的角度,挑出对生产系统影响最大的变化,逐一讲清它解决了什么问题、怎么用、什么场景受益,最后给一份升级前非生产环境验证清单。
背景:Beta 1 的定位------能测,不能上
先明确版本定位:
- Beta 1 于 2026-06-04 发布,后续可能还有 Beta 2、Release Candidate。
- GA 预计 2026 年 9-10 月,在此之前 API、目录结构、行为都还可能变。
- Beta 之间不保证升级路径,不要在生产数据上测试。
- 正确做法:用一份生产数据的副本(pg_dump 恢复或克隆环境),在非生产环境跑你的真实工作负载。
核心思路:PostgreSQL 19 的生产价值在哪
一句话概括 PostgreSQL 19 的核心方向:把 DBA 每周都在跟的运维痛点------vacuum 维护窗口、表膨胀、读写分离一致性、外键插入税------用引擎层面的能力解决掉。
按影响面排序,最值得关注的五块:
| 优先级 | 特性 | 影响面 | 你的工作负载可能受益吗 |
|---|---|---|---|
| 高 | 并行 Autovacuum + 评分系统 | 所有大表 | 有大表和多索引?受益明显 |
| 高 | REPACK / REPACK CONCURRENTLY | 膨胀治理 | 用过 pg_repack?可以去掉这个依赖 |
| 高 | JIT 默认关闭 + TOAST lz4 | 全局默认值 | OLAP 工作负载需手动恢复 JIT |
| 高 | WAIT FOR LSN | 读写分离 | 有 read-your-writes 需求?受益 |
| 中 | 外键插入性能提升 | 高写入规范化 | 有大量 FK 的写入?受益 |
运维治理:并行 Autovacuum 与 REPACK
并行 Autovacuum:大表维护不再是单线程瓶颈
PostgreSQL 18 及之前,autovacuum 对一张表的索引清理是串行的------一个 worker 逐个处理索引。对于有十几个索引的大表,autovacuum 耗时惊人,维护窗口压力巨大。
PostgreSQL 19 允许 autovacuum 使用并行 worker 处理索引清理阶段:
sql
-- 全局设置:允许 autovacuum 使用的最大并行 worker 数
ALTER SYSTEM SET autovacuum_max_parallel_workers = 3;
-- 按表设置:为特定表指定并行 worker 数
ALTER TABLE orders SET (
autovacuum_parallel_workers = 2
);
同时新增了 autovacuum 评分系统,改变了 autovacuum launcher 选择清理哪张表的策略。之前基本是 FIFO(先到阈值先清理),现在会根据死元组数量、freeze 紧急度、multixact 等因素综合评分,优先清理最需要清理的表:
sql
-- 新增系统视图:查看每张表的 autovacuum 评分
SELECT relname, score, autovacuum_count
FROM pg_stat_autovacuum_scores
ORDER BY score DESC
LIMIT 10;
还有一个容易被忽略但很实用的改进:普通查询的表扫描现在也能标记页为 all-visible(之前只有 VACUUM 和 COPY FREEZE 能做)。这意味着高读写表中被频繁扫描的页面,可见性映射更新更及时,Index-Only Scan 能更长时间保持高效。
REPACK:内置的在线表重建
VACUUM FULL 能回收膨胀空间,但它持有 ACCESS EXCLUSIVE 锁------执行期间整张表完全不可读写,对于生产表来说基本等于停服。社区方案一直是第三方扩展 pg_repack,效果好但需要额外安装、版本匹配、维护。
PostgreSQL 19 内置了 REPACK 命令,并支持 CONCURRENTLY 选项:
sql
-- 在线重建表,不持有长时间排他锁
REPACK orders CONCURRENTLY;
-- 在线重建并按指定索引聚簇
REPACK orders USING INDEX orders_created_at_idx CONCURRENTLY;
REPACK ... CONCURRENTLY 的工作原理:构建一份紧凑的新副本,同时用变更日志记录重建期间的增量修改,最后在极短的锁窗口内原子切换。读写流量在重建过程中保持正常。
注意事项 :CONCURRENTLY 用额外 I/O 和磁盘空间换取无锁------它会构建整张表的完整副本。对几百 GB 的大表,先确认磁盘有足够余量,并在生产数据的恢复副本上 benchmark 实际耗时。

监控视图增强
PostgreSQL 19 增强了 vacuum 进度监控:
sql
-- pg_stat_progress_vacuum 新增 started_by 和 mode 列
SELECT relname, phase, started_by, mode
FROM pg_stat_progress_vacuum;
-- 结果示例
-- relname | phase | started_by | mode
-- ----------+------------------+------------+------------
-- orders | scanning heap | autovacuum | normal
-- events | cleaning indexes | user | aggressive
started_by 告诉你这次 vacuum 是 autovacuum 自动触发的还是手动发起的;mode 表示激进程度。以前要区分这两者只能翻日志。
性能提升:外键插入与 AIO 自动伸缩
外键检查插入性能约 2 倍提升
任何做过规范化 schema 高频写入的团队都交过"外键税"------每条 INSERT 到带 FK 的表,都要触发引用完整性检查。订单明细引用订单、事件引用实体、日志引用用户,这些表的高频写入都被 FK 检查拖慢。
PostgreSQL 19 优化了外键约束检查路径,在高 FK 负载的批量插入场景下约 2 倍性能提升。这个优化不需要你改任何 SQL 或配置,升级即可受益。
验证方法:
sql
-- 在 PG 18 和 PG 19 上分别执行同样的批量插入
-- 对比 EXPLAIN ANALYZE 的耗时
EXPLAIN (ANALYZE, BUFFERS)
INSERT INTO order_items (order_id, product_id, quantity)
SELECT generate_series(1, 100000), 1, 1;
AIO Worker 自动伸缩
PostgreSQL 18 引入了异步 I/O 子系统。PostgreSQL 19 让它更可运维:io_method = worker 模式下,I/O worker 数量会自动伸缩:
sql
-- postgresql.conf
io_method = worker
io_min_workers = 1 -- 下限:始终保持的 worker 数
io_max_workers = 8 -- 上限:负载高时扩展到
不再需要猜一个静态 worker 数量,服务器会根据负载自动扩展和收缩 worker 池。EXPLAIN ANALYZE 也增加了 AIO 统计信息,可以看到查询有多少时间花在等待异步读取上。
其他性能改进
- COPY FROM 性能:text 和 CSV 输入使用 SIMD CPU 指令加速。
- NOTIFY 精准唤醒:只唤醒监听指定通道的 backend,不再广播唤醒大部分进程。
- 排序性能:引入 radix sort。
- Hash 索引和 GIN 索引 vacuum:使用 streaming reads 提升 bulk-deletion 性能。
复制与一致性:WAIT FOR LSN 与在线逻辑复制
WAIT FOR LSN:读写分离的"读到刚写的数据"
读写分离的经典痛点:用户在主库写了一条数据,立刻去从库读,但从库还没同步到这条数据,用户看到"数据不见了"。每个团队都绕过这个问题------粘性会话、应用层轮询、延迟容忍------但都不优雅。
PostgreSQL 19 提供了 WAIT FOR LSN 命令:
sql
-- 应用端流程
-- 步骤 1:主库写入,获取当前 LSN
-- INSERT INTO orders (...) VALUES (...) RETURNING *;
-- SELECT pg_current_wal_lsn(); -- 例如返回 0/16B3748
-- 步骤 2:从库等待该 LSN 同步完成
WAIT FOR LSN '0/16B3748';
-- 步骤 3:此时查询保证能看到刚写的数据
SELECT * FROM orders WHERE id = 42;
WAIT FOR LSN 可以等待到三种同步程度:写入(write)、刷盘(flush)、回放(replay):
sql
-- 等待到 LSN 已回放(最严格)
WAIT FOR LSN '0/16B3748';
-- 等待到 LSN 已刷盘
WAIT FOR LSN '0/16B3748' FLUSH;
-- 等待到 LSN 已写入(最快,但不保证已回放)
WAIT FOR LSN '0/16B3748' WRITE;

在线启用逻辑复制
PostgreSQL 18 及之前,启用逻辑复制需要 wal_level = logical 并重启服务器------对主库来说是计划内停机。
PostgreSQL 19 允许在 wal_level = replica 时在线启用逻辑复制,无需重启。新增只读参数 effective_wal_level 报告实际生效的 WAL 级别:
sql
-- 检查实际生效的 WAL 级别
SHOW effective_wal_level;
-- 如果 wal_level = replica 但逻辑复制已激活,这里会显示 logical
配合 序列同步(sequences 现在可以在订阅者端与发布者保持一致),基于逻辑复制的零停机大版本升级风险显著降低。
逻辑复制其他改进
sql
-- 发布所有表但排除特定表(以前只能逐个列举)
CREATE PUBLICATION all_tables FOR ALL TABLES
EXCEPT TABLE audit_log, temp_data;
-- 基于外部服务器定义订阅(连接信息集中管理)
CREATE SUBSCRIPTION my_sub SERVER foreign_server_name
PUBLICATION my_pub;
开发体验:SQL 新特性
这些不影响运维,但日常开发会用到。
ON CONFLICT DO SELECT ... RETURNING
sql
-- 以前:想拿到冲突行必须用 DO UPDATE 触发 RETURNING
INSERT INTO users (email, name) VALUES ('a@b.com', 'Alice')
ON CONFLICT (email) DO UPDATE SET name = EXCLUDED.name
RETURNING *;
-- PG 19:直接用 DO SELECT 拿到冲突行,不做无意义的 UPDATE
INSERT INTO users (email, name) VALUES ('a@b.com', 'Alice')
ON CONFLICT (email) DO SELECT
RETURNING *;
GROUP BY ALL
sql
-- 以前:非聚合列必须逐个列出
SELECT dept, role, count(*) FROM employees GROUP BY dept, role;
-- PG 19:自动按所有非聚合输出列分组
SELECT dept, role, count(*) FROM employees GROUP BY ALL;
分区管理:MERGE / SPLIT PARTITION
sql
-- 合并多个分区为一个
ALTER TABLE measurements
MERGE PARTITIONS (m_2024_01, m_2024_02, m_2024_03) INTO m_2024_q1;
-- 就地拆分一个分区为多个
ALTER TABLE measurements
SPLIT PARTITION m_2025 INTO (
PARTITION m_2025_h1 FOR VALUES FROM ('2025-01-01') TO ('2025-07-01'),
PARTITION m_2025_h2 FOR VALUES FROM ('2025-07-01') TO ('2026-01-01')
);
时间序列和多租户场景以前需要 detach/create/attach 脚本编排的操作,现在一条 DDL 搞定。
SQL/PGQ 属性图查询
PostgreSQL 19 支持用 SQL 标准的图查询语法(SQL/PGQ),直接在关系表上做图查询,不需要引入单独的图数据库:
sql
-- 定义属性图
CREATE PROPERTY GRAPH social_network
VERTEX TABLES (users KEY (id))
EDGE TABLES (
friendships SOURCE users DESTINATION users KEY (id)
);
-- 用图查询语法查找好友的好友
SELECT * FROM GRAPH_TABLE (social_network
MATCH (u1 IS users WHERE u1.name = 'Alice')
-[f1 IS friendships]->
(u2 IS users)
-[f2 IS friendships]->
(u3 IS users)
COLUMNS (u3.name AS friend_of_friend)
);
适合多跳关系查询、社交网络分析、知识图谱等场景。
默认值变更与兼容性风险(重点)
这部分是升级前必须排查的------这些默认值变更可能在不经意间影响生产。
1. JIT 默认关闭(影响最大)
sql
-- PostgreSQL 12-18:JIT 默认开启
-- PostgreSQL 19:JIT 默认关闭
SHOW jit; -- PG 19 返回 off
PostgreSQL 团队认为现有的 JIT 成本估算不可靠------对一些本不该用 JIT 的查询错误地触发了编译,导致规划开销增加但收益很小。所以 19 把默认值改成了 off。
影响:
- OLTP 工作负载:几乎不受影响,甚至更快(省去了无效的 JIT 编译开销)。
- OLAP / 分析型工作负载:如果你的大查询之前在静默享受 JIT 加速,升级后可能变慢。
应对 :如果你跑分析型工作负载,升级前先在 postgresql.conf 中显式设置 jit = on,benchmark 后再决定。
2. RADIUS 认证移除
text
# pg_hba.conf 中如果有这行,PG 19 将无法启动
host all all 0.0.0.0/0 radius
PostgreSQL 19 完全移除了 RADIUS 认证支持(因为只支持 UDP,安全性无法修复)。如果你的 pg_hba.conf 使用了 radius,升级后服务器无法启动。迁移到 LDAP、证书或其他认证方式。
3. MD5 密码认证警告
sql
-- PG 18:MD5 标记为 deprecated
-- PG 19:MD5 认证成功后会输出警告
-- 可通过 md5_password_warnings = off 关闭
MD5 密码认证正式走向废弃,每次认证成功都会记录警告。建议迁移到 SCRAM-SHA-256。
4. TOAST 压缩默认改为 lz4
sql
-- PG 18:default_toast_compression = pglz
-- PG 19:default_toast_compression = lz4
SHOW default_toast_compression; -- PG 19 返回 lz4
lz4 压缩/解压速度优于 pglz,但已有的 TOAST 数据不会自动重压缩。新写入的数据会用 lz4,存量数据保持 pglz。
5. 其他兼容性变更
| 变更 | 影响 |
|---|---|
max_locks_per_transaction 默认值 64 → 128 |
锁表内存翻倍,原来设自定义值的需检查 |
standard_conforming_strings 强制为 on |
使用 \ 转义的老 SQL 可能行为变化 |
log_lock_waits 默认开启 |
日志量增加,注意存储 |
MULE_INTERNAL 编码移除 |
使用该编码的库需 dump/restore 转换 |
| inet/cidr 默认索引 opclass 从 btree_gist 改为 GiST | 旧版 btree_gist inet/cidr 索引存在时 pg_upgrade 会失败 |
升级前验证清单
把上面的风险点整理成一份可操作的清单,在升级到 PostgreSQL 19 之前逐项检查。
sql
-- ========== 1. 检查认证方式 ==========
-- 检查 pg_hba.conf 中是否有 radius(PG 19 不再支持)
-- 命令行:grep radius $PGDATA/pg_hba.conf
-- 检查是否有 MD5 认证(会收到警告)
-- 检查 pg_hba.conf 中 method 列为 md5 的行
-- ========== 2. 检查 JIT 使用情况 ==========
-- 如果有分析型大查询,记录当前 jit 设置
SHOW jit;
SHOW jit_above_cost;
SHOW jit_inline_above_cost;
SHOW jit_optimize_above_cost;
-- 升级后如果发现分析查询变慢,先尝试 jit = on
-- ========== 3. 检查编码 ==========
-- 确认没有使用 MULE_INTERNAL
SELECT datname, pg_encoding_to_char(encoding) AS encoding
FROM pg_database
WHERE pg_encoding_to_char(encoding) = 'MULE_INTERNAL';
-- ========== 4. 检查锁配置 ==========
SHOW max_locks_per_transaction;
-- PG 19 默认改为 128,如果你之前自定义了值,需要调整为 2 倍
-- ========== 5. 检查 inet/cidr btree_gist 索引 ==========
SELECT indexrelid::regclass AS index_name,
indrelid::regclass AS table_name
FROM pg_index
WHERE indexrelid IN (
SELECT oid FROM pg_class
WHERE relname IN (
SELECT indexname FROM pg_indexes
WHERE indexdef ILIKE '%btree_gist%'
)
);
-- 如果存在 btree_gist 的 inet/cidr 索引,pg_upgrade 会失败
-- 需要在升级前删除并重建为 GiST 索引
-- ========== 6. 检查 TOAST 压缩配置 ==========
SHOW default_toast_compression;
-- PG 19 默认 lz4,确认你的应用是否依赖特定压缩行为
-- ========== 7. Benchmark 核心工作负载 ==========
-- 在生产数据的恢复副本上:
-- a) 对大表跑 autovacuum,对比 18 vs 19 的耗时
-- b) 对高 FK 写入表跑批量 INSERT,对比耗时
-- c) 对分析型查询跑 EXPLAIN ANALYZE,对比 jit on/off 的差异
-- d) 对膨胀表跑 REPACK CONCURRENTLY,验证磁盘空间和耗时
-- ========== 8. 检查逻辑复制配置 ==========
-- 如果你用逻辑复制做大版本升级:
-- a) 测试序列同步是否正确
-- b) 测试 CREATE PUBLICATION ... EXCEPT 语法
-- c) 验证在线启用逻辑复制(无需重启)

总结
PostgreSQL 19 是一个对运维友好的版本,核心价值集中在三个方向:
-
维护效率:并行 Autovacuum + 评分系统让大表清理不再串行瓶颈;内置 REPACK CONCURRENTLY 替代了 VACUUM FULL 的停机风险和 pg_repack 的外部依赖;普通扫描也能更新可见性映射,让 Index-Only Scan 更持久高效。
-
性能与一致性:外键插入约 2 倍提升、AIO worker 自动伸缩、WAIT FOR LSN 解决读写分离的 stale read------这些不需要改应用代码,升级即可受益。
-
默认值变更是最大的升级风险:JIT 关闭影响 OLAP、RADIUS 移除阻断启动、TOAST 换 lz4、锁配置翻倍------这些变化在升级前必须逐一验证,用上面的检查清单在非生产环境跑一遍你的真实工作负载。
现在 Beta 阶段就是测试的最佳时机:用一份生产数据的副本,验证哪些工作负载会受益、哪些兼容性变化需要提前排雷,等 GA 落地时你已经准备好了。