发布时间表与本文的依据
PostgreSQL 19于2026年9月24日发布了Beta 4。根据官方公告,下一步是10月初的发布候选版(RC),视测试结果,正式版(GA)也可能在10月发布。由于仍处于Beta阶段,具体行为仍可能变化。本文以Beta 4时点的官方发布说明为准。
首先需要了解一点。在Beta 4中,以下功能已从19中移除。为了稳定性和可预期的发布时间表,这些功能被推迟到之后的大版本。
- SQL/PGQ(属性图查询)
- 在线开启、关闭数据校验和
- 使用
FOR PORTION OF的时间范围UPDATE/DELETE ALTER TABLE ... MERGE PARTITIONS/SPLIT PARTITIONS
开发期间发布的解读文章中,有些把这些功能,或像GROUP BY ALL这样未出现在Beta 4发布说明中的功能,当作19的功能来介绍。升级计划请以发布说明为准进行确认。
1. REPACK:合并VACUUM FULL与CLUSTER,并可无锁执行
表因更新、删除而膨胀时,过去会使用VACUUM FULL或CLUSTER来回收空间,但两者在执行期间都会一直锁住表,难以在服务运行期间使用。19新增了取代这两个命令的REPACK,指定CONCURRENTLY选项时,可以在不阻塞读写的情况下重写表。
-- 回收空间(执行期间仍可读写)
REPACK (CONCURRENTLY, VERBOSE) orders;
-- 还可按索引顺序进行物理排序(聚簇)
REPACK (CONCURRENTLY) orders USING INDEX orders_ordered_at_idx;
工作原理如下:在创建新表期间,通过逻辑解码收集并应用这段时间内进入的变更,最强的锁(ACCESS EXCLUSIVE)只在替换文件的短暂瞬间持有。
从设计角度看,重要的是无法使用CONCURRENTLY的条件。
- 既没有主键,也没有基于索引的复制标识(replica identity)的表
- 分区表、
UNLOGGED表 - 在事务块内执行时
max_repack_replication_slots不再允许更多复制槽时
也就是说,为所有表设置主键如今关系到能否使用运维工具。此外,官方文档警告CONCURRENTLY并非MVCC安全,因此请先阅读关于执行期间长时间运行的事务所看到的数据的注意事项(文档第13.6节)再使用。
2. CHECK约束也可在ENFORCED / NOT ENFORCED之间切换
从PostgreSQL 18开始,可以将CHECK约束和外键约束声明为NOT ENFORCED。在19中,可以通过ALTER CONSTRAINT事后更改CHECK约束是否生效(到18为止只有外键可以)。切换为ENFORCED时,会先确认现有行是否遵守规则,再将其应用于新行。
-- 对现有数据中可能存在违规的规则,先只做声明
ALTER TABLE orders
ADD CONSTRAINT orders_amount_positive CHECK (amount_krw > 0) NOT ENFORCED;
-- 清理违规数据后再生效
ALTER TABLE orders ALTER CONSTRAINT orders_amount_positive ENFORCED;
可用于分阶段迁移:先把规则作为文档写进模式,待数据清理完成后再真正强制执行。
3. 外键检查变得更快
发布说明概述在性能改进项中列出了更快的外键检查。这一变化的方向是降低外键较多的规范化模式中的写入成本(改进幅度因工作负载而异,请自行测量)。此外,在CREATE SCHEMA中,现在可以通过外键提前引用尚未创建的表。
4. 升级前需要确认的行为变化
以下是兼容性条目中可能影响应用程序的内容。
standard_conforming_strings始终开启:如果有代码依赖于将普通字符串字面量中的反斜杠解释为转义字符的行为,需要进行确认- 没有结果行的
json_array()调用返回空JSON数组而不是NULL:用IS NULL判断"不存在"的查询,结果会发生变化 max_locks_per_transaction默认值64 → 128- 数据库、角色、表空间名称中禁止使用换行符(CR、LF)
inet、cidr的默认索引opclass从btree_gist改为GiST:如果一直使用btree_gist扩展为这些类型创建索引,请进行确认
此外,bytea与uuid之间的类型转换(cast)现已被允许,可以直接转换以二进制形式接收的UUID。
5. 复制与读取一致性
序列值的逻辑复制。 逻辑复制现在也会复制序列值。通过逻辑复制进行大版本升级时,在切换前手动对齐序列值的工作会减少。此外,当wal_level为replica时,无需重启服务器即可启用逻辑复制。
用WAIT FOR LSN实现"读己之写"。 在写入发往主服务器、读取发往副本(备库)的架构中,刚写入的数据可能尚未出现在副本上。使用新的WAIT命令,可以在副本上等待,直到特定的WAL位置被应用为止。
-- 主服务器:写入后立即确认当前WAL位置
SELECT pg_current_wal_lsn(); -- 例:0/306EE20
-- 副本:应用到该位置后再读取(最多等待1秒)
WAIT FOR LSN '0/306EE20' WITH (TIMEOUT '1s');
SELECT * FROM orders WHERE id = 1001;
指定NO_THROW选项后,超时时不会报错,而是返回状态(success、timeout等)。
6. 其他变化
- autovacuum使用并行工作进程清理索引,并引入评分机制,优先处理最需要处理的表
- 新增jsonpath字符串方法:
lower()、upper()、initcap()、replace()、split_part()、btrim()、ltrim()、rtrim() - 用于固定和控制规划器决策的**
pg_plan_advice扩展,以及按查询自动应用的pg_stash_advice**
用Erdmates提前检查
升级到19之前,先把模式导入为ERD,就能一目了然地确认没有主键标记的表(无法使用REPACK CONCURRENTLY的表)以及外键关系。Erdmates可以导入PostgreSQL的CREATE TABLE、COMMENT ON语句并绘制成ERD。
总结
在PostgreSQL 19中,模式设计者首先要关注三件事:为所有表设置主键,以便使用REPACK CONCURRENTLY;在分阶段迁移中利用CHECK约束从NOT ENFORCED → ENFORCED的切换;在升级前测试standard_conforming_strings、json_array()等行为变化。在正式发布之前,功能列表仍可能变化,请再次确认最终的发布说明。