每隔一个大版本,PostgreSQL 都会塞进一堆新功能,但大部分你日常根本碰不到。Christophe Pettus 在最近的文章里挑出了 PG19 beta 中四个"你会真切感受到"的改动——不是纸面上的性能数字,而是直接消除运维噩梦、减少深夜告警的实招。下面逐个拆解,并给出可以直接跑的检查和配置命令。
MultiXact 64 位:终结"不 vacuum 就死"的倒计时
这是四个特性里影响最深远的一个。PostgreSQL 用 MultiXact 来跟踪一行记录上多个锁的持有者(比如多个事务同时 SELECT ... FOR SHARE)。旧版 MultiXact 的成员 ID 只有 32 位,上限约 2³² ≈ 4.29 亿条。一旦逼近上限,数据库就会进入所谓的 "vacuum or die" 模式——你必须立刻对整库做激进 vacuum,否则 MultiXact ID 环绕后,整库写入直接卡死。
这个故障模式存在了二十多年。它的可怕之处在于:
- 环绕不像磁盘满那样有明确预兆,往往在
pg_multixact/members文件暴涨时才发现。 - 紧急 vacuum 期间业务写入严重降速,大表可能要跑数小时。
- 32 位上限在高并发行锁场景下(大量
FOR KEY SHARE/FOR SHARE)几年就能耗尽。
PG19 把成员 ID 扩到 64 位,上限跳到 2⁶⁴,环绕风险在实际意义上消失了。你不再需要盯着 pg_multixact 目录大小心惊肉跳,也不再需要为了防环绕而配置过度激进的 autovacuum 参数。
下面这条查询可以直接检查你当前库的 MultiXact 消耗情况,跑一下看看离旧上限有多近:
-- 查看当前 MultiXact 成员数与 32 位上限的差距
SELECT
relname,
relmultixact_members::bigint AS current_members,
4294967295 AS old_32bit_limit,
ROUND(relmultixact_members::bigint / 4294967295.0 * 100, 4) AS pct_of_limit
FROM pg_class
WHERE relmultixact_members > 0
ORDER BY pct_of_limit DESC
LIMIT 10;
如果你看到 pct_of_limit 超过 50%,在 PG17 及以前版本上就该立刻安排全库 vacuum。升级到 PG19 后,这个数字再大也不用慌了。
并行 Autovacuum:大表不再排队等清理
旧版 autovacuum 是单进程逐表清理。当库里有几张十亿级大表时,一张表的 vacuum 就能跑几十分钟,其他表只能排队。排队期间,死元组堆积,查询变慢,事务 ID 环绕风险也在累积——这就是为什么很多团队被迫手动 VACUUM。
PG19 引入了 并行 autovacuum:多个 worker 可以同时对不同表做 vacuum,不再串行等待。这对以下场景效果立竿见影:
- 写入密集的多张大表(订单、日志、事件表)。
- 分区表:每个分区可以独立被不同 worker 处理。
- autovacuum 长期跟不上死元组产生速度的库。
配置方式很直接——在 postgresql.conf 中调大 worker 数量:
# postgresql.conf — 并行 autovacuum 配置
autovacuum_max_workers = 6 # 旧版默认 3,PG19 建议按 CPU 核数上调
autovacuum_naptime = 30s # 检查间隔,写入密集库可缩短到 15s
log_autovacuum_min_duration = 500ms # 记录超过 500ms 的 vacuum,方便观察并行效果
改完后 reload 即生效:
pg_ctl reload -D /var/lib/postgresql/19/main
# 或者
psql -c "SELECT pg_reload_conf();"
然后观察日志,你会看到多条 automatic vacuum of ... 同时出现,时间戳重叠——这就是并行生效的证据。
逻辑复制容错控制:主库切换不再丢数据
第三个特性是逻辑复制(logical replication)的 failover 控制。旧版逻辑复制在主库切换时有一个硬伤:standby 升为主后,旧的逻辑复制 slot 不会自动迁移,订阅端要么断连重配,要么丢数据。这让逻辑复制在 HA 场景下几乎不可用——大家只能退回物理复制。
PG19 给 pg_replication_slots 加了 failover 属性。标记为 failover = true 的逻辑 slot 会随主库切换自动流转到新主,订阅端无需重配就能继续拉数据。
创建一个带 failover 的发布和订阅:
-- 主库:创建发布,并启用 failover slot
CREATE PUBLICATION my_pub FOR TABLE orders, order_items
WITH (failover = true);
-- 订阅端:创建订阅,同样指定 failover
CREATE SUBSCRIPTION my_sub
CONNECTION 'host=primary.example.com dbname=mydb'
PUBLICATION my_pub
WITH (failover = true, streaming = 'parallel');
切换后,新主上的 slot 自动就绪,订阅端 reconnect 后无缝续接。这对以下架构是关键一步:
- 跨数据中心逻辑同步(只同步指定表)。
- 从主库向分析库 / 缓存库做增量同步,同时主库有 HA 切换。
- 微服务间数据分发,不能因为主库切换而中断。
更透明的进度监控:pg_stat_progress_vacuum 增强
第四个特性是 vacuum 进度监控的增强。旧版 pg_stat_progress_vacuum 只显示当前正在 vacuum 的表,但 autovacuum worker 的调度、排队、跳过等行为完全黑盒。DBA 只能从日志拼凑线索。
PG19 扩展了进度视图,增加了更多阶段和细节字段,让你能直接看到:
- 哪些表正在被哪个 worker vacuum。
- 当前处于哪个阶段(扫描、索引清理、截断等)。
- 已处理死元组数 / 预估总数的比例。
-- PG19:查看所有 autovacuum worker 的实时进度
SELECT
pid,
datname,
relname,
phase,
heap_blks_total,
heap_blks_scanned,
index_vacuum_count,
dead_tuple_count,
dead_tuple_percent
FROM pg_stat_progress_vacuum
ORDER BY pid;
这让你判断"vacuum 到底卡在哪"不再靠猜。如果某张表 heap_blks_scanned 长时间不动,说明 IO 卡住或锁冲突;如果 dead_tuple_percent 持续走高但 worker 数量不够,就该上调 autovacuum_max_workers。
升级前的实操清单
PG19 是 beta,生产不要直接上,但测试环境现在就该跑一轮:
- 备份 MultiXact 基线:升级前用上面的查询记录各表
relmultixact_members,升级后对比确认 64 位生效。 - 压测并行 autovacuum:在测试库造两张亿级表,持续写入 + 删除,观察
pg_stat_progress_vacuum中多 worker 并行情况,对比 PG17 下单 worker 的吞吐差异。 - 演练逻辑复制 failover:搭建主 + standby + 订阅端三节点,用
failover = true配逻辑复制,做一次 switchover,验证订阅端是否自动续接、无数据丢失。 - 调参:
autovacuum_max_workers从 3 调到 6-8(视 CPU 核数),autovacuum_naptime缩短,观察写入密集场景下死元组堆积速度是否明显下降。
四个特性的共同点:它们不改变 SQL 语法,不改变应用代码,但直接消除了运维中最让人焦虑的几种故障模式——环绕死锁、vacuum 排队、复制断连、进度黑盒。如果你是 DBA 或后端工程师负责 PG 库的稳定性,PG19 值得尽早进入测试计划。