PostgreSQL 19 的 REPACK:一条命令顶掉 VACUUM FULL、CLUSTER 和 pg_repack
PostgreSQL 19 的 GA 计划是 2026-11-19,RC1 在 2026-10-15。这个版本里对日常运维影响最大的一项,是新增的 REPACK 命令:它替代 VACUUM FULL 与 CLUSTER,旧命令保留以兼容既有脚本。更关键的是 REPACK (CONCURRENTLY) 不拿 ACCESS EXCLUSIVE 锁,重建期间读写照常进行。
它解决的是什么问题
表膨胀之后的整理,过去有三条路:VACUUM FULL、CLUSTER、第三方 pg_repack。前两个都要排他锁,业务得停或得挑窗口;第三个要装扩展、建触发器或走逻辑复制通道。PG19 把这三件事合并进一个 in-core 命令,CONCURRENTLY 形式不再阻塞读写。
怎么工作
REPACK (CONCURRENTLY) 的重建期与切换期是分开的:
- 重建阶段,并发读写继续落在原 heap 上,新表按原表结构重写一份;
- 期间通过复制 slot 收集原表上的变更,把增量同步到新表;
- 最后做一次切换,把表指向新 heap。
复制 slot 的池子由新增的服务变量 max_repack_replication_slots 控制。也就是说,并发重建不是免费午餐,它消耗的是复制 slot 这类实例级资源,同时进行的并发 REPACK 数量直接受这个参数约束。实例上已有逻辑复制、物理复制或备份正在占用 slot 时,这个参数的余量要先算清楚。
代价
三笔账要提前算:
- WAL 膨胀。重建本身就要写大量 WAL,追加的增量同步还会再放大一轮。WAL 归档、备库回放、跨区传输的带宽都会被这条命令拉满。
- slot 池。
REPACK (CONCURRENTLY)依赖复制 slot,max_repack_replication_slots给小了会失败或排队,给大了会把 slot 资源从逻辑复制那边挤走。 - 磁盘双份。切换前新旧两份数据同时存在,表有多大,峰值就要多预留接近一份的空间,索引一并计入。
所以大表上的 REPACK (CONCURRENTLY) 是「用 WAL、slot 和磁盘换业务无感」,而不是零成本操作。
命令示例
-- 重建表(对应 VACUUM FULL 的整理目的)
REPACK orders;
-- 并发重建,不阻塞读写;需要可用的 repack 复制 slot
REPACK (CONCURRENTLY) orders;
-- 按索引重排,对应 CLUSTER 的用法
REPACK orders USING orders_created_at_idx;
slot 池按实例规模设置,例如:
max_repack_replication_slots = 4
这个值要与实例上同时运行的并发 REPACK 数量、以及已有的复制/备份 slot 需求一起决定,不要照抄。
上线前检查
- 磁盘:目标表数据 + 索引的近似大小,剩余空间要能容纳新旧两份,并留出 WAL 的余量;
- slot:确认
max_repack_replication_slots有余量,且不会挤掉逻辑复制与备份使用的 slot; - WAL 链路:归档目录、备库延迟阈值、跨区带宽能否承受短时激增;
- 锁与长事务:虽然不拿
ACCESS EXCLUSIVE,切换阶段仍要能及时拿到所需锁,先清掉长事务再执行; - 灰度:先在低峰期用小表跑一次,观察 WAL 生成速率与复制延迟,再上大表。
PG19 其他相关变更
同一版本还有几项与运维路线相关:
pg_plan_advice扩展可生成 plan advice 字符串,通过EXPLAIN (PLAN_ADVICE '...')一次性注入;pg_stash_advice按 query id 自动应用;- autovacuum 支持并行,参数为
autovacuum_max_parallel_workers与每表的autovacuum_parallel_workers,新增pg_stat_autovacuum_scores视图和autovacuum_*_score_weight系列参数; - 新增
pg_stat_recovery、pg_stat_lock视图; - 逻辑复制支持序列值(
ALL SEQUENCES、REFRESH SEQUENCES); wal_level=replica时可自动启用逻辑复制,并新增effective_wal_level;WAIT FOR LSN支持备库上的 read-your-writes;io_method=worker时按io_min_workers/io_max_workers自动扩缩;- JIT 默认关闭,
default_toast_compression默认改为 lz4; - 移除 RADIUS。
RC 期间修掉的问题里,与本文直接相关的是 REPACK 的崩溃、无效索引与物化视图行为、权限与报错;另有 WAIT FOR 的死锁与隔离级别报错,以及 parallel autovacuum 的多项修复。计划在生产上使用 REPACK (CONCURRENTLY) 的实例,建议直接以 GA 版本或包含这些修复的 RC 为基线。