PostgreSQL BDR复制槽:导致其变为非活动状态的原因排查
作为经常和PostgreSQL BDR打交道的人,我完全懂你这种看着一堆非活动复制槽占满磁盘的头疼!给你梳理下我排查这类问题的思路,还有要检查的工作流/代码点:
先明确BDR复制槽变非活动的常见原因
BDR的复制槽和普通流复制槽逻辑类似,但因为是多主架构,还有额外的节点同步逻辑,常见触发非活动的场景有:
- 对等节点离线过久:超过BDR的超时阈值后,主库会标记对应复制槽为非活动
- BDR节点异常退出:比如直接断电、OOM kill,没有走正常的节点下线流程,导致复制槽残留
- 复制连接被强制中断:比如防火墙拦截、网络闪断,且节点没有自动重连成功
- 手动创建了BDR复制槽但未关联到正常节点:比如测试时手动建槽后没清理
第一步:先排查当前复制槽的状态和影响
先跑这条SQL,把所有非活动的BDR复制槽列出来,还能看到它们占用的磁盘空间:
-- PostgreSQL 10+ 用pg_wal开头的函数,老版本用pg_xlog SELECT slot_name, slot_type, active, pg_size_pretty(pg_wal_location_diff(pg_current_wal_location(), restart_lsn)) AS retained_wal_size FROM pg_replication_slots WHERE slot_type = 'bdr' AND active = false;
然后去主库的PostgreSQL日志里搜这些槽的名字,找有没有类似replication slot "xxx" marked as inactive的日志,旁边通常会附带原因(比如节点失联多久)。
另外用BDR自带的函数检查节点状态,确认这些非活动槽对应的节点是不是真的已经下线:
SELECT node_name, node_status FROM bdr.node_status();
检查工作流/代码里的潜在问题
这部分是关键,不然清理完还会再出现:
- 临时节点没清理:有没有运维脚本或者测试流程里临时搭建BDR节点,用完后只关机没执行
bdr.drop_node()?这种情况最容易残留非活动槽 - 应用/工具的异常逻辑:有没有程序会自动创建BDR复制槽?比如某些备份工具或者同步工具,如果逻辑有问题,创建后没维护连接,槽就会变非活动
- BDR配置不合理:检查
bdr.slots_cleanup_interval参数,这个是BDR自动清理异常非活动槽的间隔,默认3600秒(1小时),如果设置得太大,非活动槽会一直占磁盘;另外bdr.node_timeout如果设置得太小,可能会误判节点离线 - 强制中断连接的操作:有没有运维人员手动执行
pg_terminate_backend()杀掉BDR的复制连接?如果杀完没处理对应的槽,也会导致非活动状态
清理非活动槽的正确姿势
注意:一定要先确认对应的BDR节点已经永久下线,不需要再同步了,不然删了槽之后节点再上线就彻底没法同步了!
- 如果对应的节点还在
bdr.node_status()里,先执行节点删除:
这个命令会自动清理对应的复制槽,是最安全的方式SELECT bdr.drop_node(node_name := 'your_node_name', drop_slot := true); - 如果节点已经不在列表里,直接删除复制槽:
批量清理的话,可以生成执行语句再跑:SELECT pg_drop_replication_slot('your_slot_name');SELECT format('SELECT pg_drop_replication_slot(''%s'');', slot_name) FROM pg_replication_slots WHERE slot_type = 'bdr' AND active = false;
预防措施(避免再出现)
- 加监控:监控
pg_replication_slots里的active状态和retained_wal_size,一旦出现非活动槽且占用空间超过阈值就告警 - 规范节点下线流程:任何BDR节点下线,必须先执行
bdr.drop_node(),禁止直接关机/销毁实例 - 调整BDR配置:把
bdr.slots_cleanup_interval调小一点,比如改成300秒(5分钟),让系统更快清理异常槽;根据网络稳定性调整bdr.node_timeout,避免误判
内容的提问来源于stack exchange,提问作者dot
相关产品推荐
相关产品推荐

