replay_lag是判断逻辑复制订阅端是否跟上的关键指标,表示WAL解码完成但未应用的时间差;write_lag仅反映写入延迟,意义不大;持续增大(如>30s)说明apply进程卡住。

查看 pg_stat_replication 中的 replay_lag 和 write_lag
PostgreSQL 10+ 的逻辑复制中,pg_stat_replication 视图里的 replay_lag 是判断订阅端是否真正“跟上”的关键指标。它表示 WAL 已写入并解码完成、但尚未应用到本地表的时间差;而 write_lag 只反映 WAL 写入延迟,对逻辑复制意义不大。
- 如果
replay_lag持续增大(比如 > 30s),说明 apply 进程卡住了,不是网络或发送端问题 -
state字段必须是streaming,否则连接已断或配置失效 - 注意:该视图只在发布端可见;订阅端要查
pg_stat_subscription
检查 pg_stat_subscription 中的 last_msg_send_time 和 last_msg_receipt_time
订阅端自身状态得看 pg_stat_subscription。这个视图能告诉你消息是否被接收、是否在 apply 队列里积压。
-
last_msg_receipt_time和当前时间差过大 → 网络抖动或发布端发送异常 -
last_msg_send_time接近当前时间但last_msg_receipt_time落后 → 网络丢包或防火墙限速 -
substate是d(down)或u(uninstalled)→ 订阅已失效,需ALTER SUBSCRIPTION … REFRESH PUBLICATION或重建
确认 apply 进程是否在运行且无锁等待
逻辑复制的 apply 进程本质是一个后台 worker,名字类似 logical replication worker for subscription 。它一旦被阻塞,延迟就会累积。
- 在订阅端执行
SELECT * FROM pg_stat_activity WHERE backend_type = 'background worker',确认该进程存在且state = 'active' - 若
wait_event_type = 'Lock'且wait_event = 'relation'→ 正在等某张表的 AccessExclusiveLock,常见于并发 DDL(如ALTER TABLE)或长事务持有锁 - 若
state = 'idle in transaction'→ apply 进程卡在某个事务里没提交,可能是触发器或约束校验失败导致回滚重试
排查目标表上的约束、触发器与索引维护开销
逻辑复制 apply 是单线程按 WAL 顺序逐条执行的,任何在 apply 过程中触发的额外操作都会放大延迟。
- 启用
log_statement = 'ddl'+log_min_duration_statement = 1000,观察 apply 期间是否有慢 DDL 或长事务日志 - 删除或禁用非必要触发器:
ALTER TABLE t DISABLE TRIGGER ALL(仅测试时用) - 检查主键/唯一索引是否缺失:apply 依赖索引快速定位行,缺失会导致全表扫描式更新
- 大批量 INSERT/UPDATE 通过
INSERT ... ON CONFLICT或UPSERT实现,避免先 DELETE 再 INSERT(后者需两次索引查找)
延迟高往往不是单一原因,而是 apply 线程在锁、索引、触发器、约束之间反复卡顿。最常被忽略的是:订阅端开启了 synchronous_commit = on,导致每条变更都等 WAL 刷盘,而物理复制默认关掉它——逻辑复制也应设为 off 或 local。










