PostgreSQL的逻辑复制功能依赖一组后台工作进程(logical replication worker)来完成发布端与订阅端之间的数据同步。这些进程的数量并不是无限的,而是由参数max_logical_replication_workers统一控制。理解这个参数的工作机制,对排查订阅创建失败、表同步卡住等问题非常关键。

max_logical_replication_workers的工作原理
max_logical_replication_workers是一个静态参数,默认值为64,表示整个实例中允许同时存在的逻辑复制相关worker进程的最大数量。它管控的范围不只是普通的apply worker,还包括表同步阶段产生的table synchronization worker。也就是说,所有订阅的apply worker和sync worker共享这一个总池子。
具体分配规则是这样的:每创建一个订阅,系统会为它启动一个apply worker进程,负责接收并回放该订阅的数据流。当订阅新加入一张表需要做初始数据拷贝时,apply worker会为这张表(或一批表)申请一个table sync worker来做全量同步。这就意味着一个订阅在某些时刻可能占用不止一个worker名额。假设你有60个订阅,每个订阅又恰好有多张表在同步,64个默认名额很快就会被耗尽。
需要特别注意的是,这个参数的分配还发生在更深一层:每个逻辑复制worker在解码端实际上对应一个walsender进程,而walsender的数量又受max_wal_senders限制。因此规划时要保证max_wal_senders不小于max_logical_replication_workers加上物理流复制的连接数,否则可能出现worker想启动却拿不到walsender槽位的尴尬情况。
worker耗尽时的典型表现与排查方法
当worker名额被占满时,最直观的表现是新建订阅后迟迟没有数据同步过来,日志中会出现类似out of logical replication worker slots或could not fork worker process的报错。已有的订阅如果新增表,也会发现表一直处于初始化状态,pg_subscription_rel视图中对应表的srsubstate长期停留在i或d阶段。
排查时可以从两个视图入手。第一个是pg_stat_activity,过滤查询中backend_type为logical replication worker的进程数量:
SELECT pid, backend_type, backend_start FROM pg_stat_activity WHERE backend_type LIKE 'logical replication%';
第二个是pg_stat_subscription,可以看到每个订阅的worker工作状态、最近接收和回放的LSN位置。如果发现某个订阅的relstate一直不推进,而worker总数已经逼近上限,基本可以确认是worker池不够用了。另外也可以直接查询pg_subscription_rel确认各表的同步状态,判断是不是有大量表卡在同步阶段占用了sync worker。
参数配置建议与注意事项
这个参数只能通过修改postgresql.conf(或命令行)调整,需要重启实例才能生效,不能简单的用ALTER SYSTEM加SELECT pg_reload_conf()在线生效,这也是它容易被人忽略的原因。配置时建议先用一个简单的估算公式:订阅总数,加上高峰期可能同时做表同步的表数量,再预留20%左右的余量。
举个例子,假设生产库有40个订阅,每个订阅平均100张表,新上订阅时允许8张表并行同步,那么至少需要40 + 8到16的余量,也就是64个左右。同时sync worker的并行度还受max_sync_workers_per_subscription限制(默认2),适当调大它可以加快单订阅的初始同步速度,但前提是总池子也要相应扩大,否则只是把竞争从订阅内部转移到了订阅之间。
最后提醒两点:一是每个worker进程都是实实在在的操作系统进程,会消耗内存和CPU,盲目调到几百上千并不可取,物理内存要按每个worker几十MB的级别预留;二是调整后记得同步检查max_wal_senders、max_replication_slots这两个关联参数,逻辑订阅在发布端会创建复制槽,槽位不足同样会导致订阅无法正常工作。三个参数配合调整,逻辑复制体系才能稳定运行。
PostgreSQL逻辑复制max_logical_replication_workers修改时间:2026-09-07 05:52:24