replay_lag是判断逻辑复制订阅端是否跟上的关键指标,表示WAL解码完成但未应用的时间差;write_lag仅反映写入延迟,意义不大;持续增大(如>30s)说明apply进程卡住。
PostgreSQL 10+ 的逻辑复制中,pg_stat_replication 视图里的 replay_lag 是判断订阅端是否真正“跟上”的关键指标。它表示 WAL 已写入并解码完成、但尚未应用到本地表的时间差;而 write_lag 只反映 WAL 写入延迟,对逻辑复制意义不大。
replay_lag 持续增大(比如 > 30s),说明 apply 进程卡住了,不是网络或发送端问题 state 字段必须是 streaming,否则连接已断或配置失效 
pg_stat_subscription 订阅端自身状态得看 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 进程本质是一个后台 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(仅测试时用) INSERT ... ON CONFLICT 或 UPSERT 实现,避免先 DELETE 再 INSERT(后者需两次索引查找) 延迟高往往不是单一原因,而是 apply 线程在锁、索引、触发器、约束之间反复卡顿。最常被忽略的是:订阅端开启了 synchronous_commit = on,导致每条变更都等 WAL 刷盘,而物理复制默认关掉它——逻辑复制也应设为 off 或 local。