首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >别抢槽位了, REPACK 和 逻辑复制 你们各玩各的!

别抢槽位了, REPACK 和 逻辑复制 你们各玩各的!

作者头像
用户4035096
发布2026-07-10 09:30:13
发布2026-07-10 09:30:13
50
举报

别抢槽位了, REPACK 和 逻辑复制 你们各玩各的!


场景引入:一个让你半夜被叫醒的报错

凌晨 2 点 ( AI 这货为了流量, 每次都捏造凌晨2点, 你不睡人家也不睡吗? ),你被一条告警吵醒:

代码语言:javascript
复制
ERROR: all replication slots are in use

你赶紧登录数据库检查,发现 max_replication_slots = 10,10 个槽全被逻辑复制订阅占满了。

但问题是——业务最近在跑大表的 REPACK CONCURRENTLY,每次 REPACK 都需要一个临时复制槽。现在它抢不到槽,直接报错了。

你陷入了两难:

  • **加大 max_replication_slots**?会影响 WAL 保留开销,所有订阅要重新对接
  • 禁止 REPACK?业务不允许,表空间告急
  • 半夜手动干预?这不是长久之计

这是很多 PostgreSQL DBA 真实经历过的痛点。

而现在,这个提交 e76d8c749c3 引入了一个新参数,彻底终结了这个问题。


核心解决方案:两个池子,各管各的

新参数叫 **max_repack_replication_slots**,专门给 REPACK 命令预留一批独立的复制槽。

形象地说:

以前:所有复制槽是一整个大池子,逻辑复制和 REPACK 互相抢现在:复制槽被切成两半,一边是"逻辑复制专用",一边是"REPACK 专用",各用各的,互不干扰


技术原理(通俗版)

复制槽的"分区居住"

PostgreSQL 的复制槽在内存里是一个连续的数组。

改动之前:所有槽混在一起,谁都能申请

改动之后:数组从逻辑上被分成两段

代码语言:javascript
复制
[0 ~ max_replication_slots)        -> 逻辑复制订阅专用
[max_replication_slots ~ max_replication_slots + max_repack_replication_slots)  -> REPACK 专用

当 REPACK 申请槽时,它只在后半段找空闲槽;当逻辑复制订阅申请槽时,它只在前半段找。

默认值 5,开箱即用

max_repack_replication_slots 默认值是 5,意味着最多支持 5 个并发 REPACK 同时运行。

对大多数业务场景来说,这个数字够用了。如果真的需要更多并发,调整这个参数即可,不需要动 max_replication_slots

报错信息更精准了

当槽耗尽时,新的 hint 会直接告诉你应该调哪个参数:

  • 如果是逻辑复制槽不够 → 提示调大 max_replication_slots
  • 如果是 REPACK 槽不够 → 提示调大 max_repack_replication_slots

不再需要猜了。


一图理解新旧方案对比

代码语言:javascript
复制
【改动前:所有槽混在一个池子里】

max_replication_slots = 10
┌─────────────────────────────────────┐
│ [槽1][槽2][槽3][槽4][槽5][槽6][槽7][槽8][槽9][槽10] │
└─────────────────────────────────────┘
   ↑逻辑复制订阅×8        ↑REPACK×2(用完了)

结果:REPACK 和订阅争抢剩下的 2 个槽,容易报错


【改动后:两个独立池子】

max_replication_slots = 10(逻辑复制专用)
max_repack_replication_slots = 5(REPACK专用)
┌──────────────────┬─────────────┐
│ [槽1~10 逻辑复制] │ [槽11~15 REPACK] │
└──────────────────┴─────────────┘
   8个订阅用掉8个        2个REPACK用掉2个
   还剩2个空闲            还剩3个空闲

结果:各用各的,互不影响

配置示例

postgresql.conf 中添加一行即可:

代码语言:javascript
复制
# 逻辑复制订阅用
max_replication_slots = 10

# REPACK 专用(新增)
max_repack_replication_slots = 5

注意:这是一个 PGC_POSTMASTER 级别参数,必须在服务器启动前设置,不支持 ALTER SYSTEM 动态修改。

如果想彻底禁止 REPACK 使用任何槽

代码语言:javascript
复制
max_repack_replication_slots = 0

此时任何 REPACK 命令都会直接报错:

代码语言:javascript
复制
ERROR: REPACK can only be used if "max_repack_replication_slots" > 0

适合哪些场景

场景 1:同时跑多个逻辑复制订阅 + 并发 REPACK

这是最典型的场景。比如你有 8 个逻辑复制订阅,同时业务在多个大表上跑 REPACK。

以前:10 个槽,8 个订阅占满,REPACK 抢剩下 2 个,高并发时必报错现在:REPACK 有独立的 5 个槽专用池,互不干扰

场景 2:REPACK 并发数较高

有些业务会同时对多张大表做 REPACK,默认 5 个并发基本够用。不够时只需调大 max_repack_replication_slots不需要动逻辑复制侧的任何配置

场景 3:精细化管控

通过设置 max_repack_replication_slots = 0,DBA 可以精确控制是否允许 REPACK 使用复制槽,比以前的"一刀切"更灵活。


一个提醒

max_repack_replication_slots 是静态参数,调整需要重启实例。

建议在上线前评估好两个池的大小:

  • max_replication_slots:根据逻辑复制订阅数量预留
  • max_repack_replication_slots:根据并发 REPACK 数量预留(默认 5)

如果你发现默认的 5 不够用,说明业务对 REPACK 的依赖程度很高,或许值得重新审视一下表的设计是否合理。


总结

这个改动的核心思想是资源隔离——让专业工具各司其职。

  • 逻辑复制订阅继续用 max_replication_slots,行为完全不变
  • REPACK有了专属的 max_repack_replication_slots,不再和业务抢槽
  • 错误提示更精准,排障更直接
  • 向后兼容,已有部署不受影响

这是 PostgreSQL 在运维灵活性上的又一次小步改进。对于有高并发 REPACK 需求的系统,这是一个值得升级到位的功能。


相关提交e76d8c749c3152657711ed733f0aea61c0e36a91适用版本:PostgreSQL 19+(待正式发布)


如果文章有帮助,欢迎转发给身边的 PostgreSQL DBA 朋友。

有疑问或踩过类似坑的,欢迎留言区交流。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2026-04-14,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 digoal德哥 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 别抢槽位了, REPACK 和 逻辑复制 你们各玩各的!
    • 场景引入:一个让你半夜被叫醒的报错
    • 核心解决方案:两个池子,各管各的
    • 技术原理(通俗版)
      • 复制槽的"分区居住"
      • 默认值 5,开箱即用
      • 报错信息更精准了
    • 一图理解新旧方案对比
    • 配置示例
    • 适合哪些场景
      • 场景 1:同时跑多个逻辑复制订阅 + 并发 REPACK
      • 场景 2:REPACK 并发数较高
      • 场景 3:精细化管控
    • 一个提醒
    • 总结
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档