pgoutput复制延迟更低,实测1k tps下端到端延迟常在20ms内,而pglogical因多一层逻辑解析和冲突处理通常为80–150ms,但仅适用于纯追加、无ddl、无跨库映射的简单postgres到postgres拓扑。

pglogical 和 pgoutput 哪个复制延迟更低
pgoutput 原生协议直接走 WAL 解析 + 流式发送,不经过 sql 层,延迟天然比 pglogical 低 50–80ms(实测 1k TPS 场景下,pgoutput 端到端延迟常在 20ms 内,pglogical 多一层逻辑解析和冲突处理,通常 80–150ms)。但这个优势只在“纯追加、无 DDL、无跨库映射”的简单拓扑里成立。
容易踩的坑:
- pgoutput 是 postgresql 内置协议,只能用于
postgres到postgres的复制,不支持写入 mysql/ES/CSV 等外部系统 - pglogical 虽慢一点,但支持表级过滤、列裁剪、DDL 同步(需显式启用)、跨版本兼容(如
12 → 15),这些功能一开,延迟会再+30–100ms,但业务可用性大幅提升 - 别在 pgoutput 上硬套逻辑订阅——它没有
pg_logical_slot_get_changes()接口,强行轮询 slot 会导致 WAL 积压和主库 IO 暴涨
wal2json 输出 jsON 时 CPU 占用为什么突然飙升
wal2json 默认输出完整变更事件(含旧值、新值、事务元数据),字段越多、更新越密,json 序列化开销越大。实测单核上 5k UPDATE/s 就可能吃满 CPU,尤其当字段含 jsonb 或长文本时,序列化耗时呈非线性增长。
优化建议:
- 用
add-tables显式指定需要监听的表,避免全库扫描 - 设置
include-transaction为false关闭事务头包装,省掉一层嵌套 - 禁用旧值:启动 slot 时传
include-previous=off,能降 20–40% CPU - 别在生产 slot 上直接消费:用
pg_recvlogical拉取后交由下游异步解析,避免阻塞 WAL 清理
三者对主库 WAL 归档和磁盘压力的影响差异
pgoutput 最轻量:它复用物理复制通道,不创建逻辑 slot,不触发额外 WAL 记录(如 logical decoding 所需的 logical_rewrite 标记)。pglogical 和 wal2json 都依赖逻辑 slot,会强制开启 logical_decoding,导致以下行为:
- 所有 DML 语句生成额外 WAL 记录(含 tuple data),WAL 日志体积平均增加 15–30%
- 即使没消费者读取 slot,WAL 也不能被
pg_wal回收,容易填满磁盘(错误信息:could not extend file "pg_wal/...": No space left on device) - wal2json 若配置了
include-timestamp=true,还会触发每事务一次系统时钟调用,高并发下有微小但可测的 syscall 开销
什么时候该放弃 wal2json 改用 pglogical
当你需要稳定同步 DDL(比如 ALTER TABLE ADD column 自动生效)、或必须做行级冲突检测(如双写合并)、或下游是另一个 PostgreSQL 实例并希望复用其索引/约束机制时,wal2json 就不合适了——它只输出 JSON 字符串,没法自动建表、没法判断主键冲突、也没法把 INSERT 转成 ON CONFLICT DO UPDATE。
典型信号:
- 下游消费程序开始手写
CREATE TABLE模板和字段映射逻辑 - 出现
duplicate key violates unique constraint错误且无法靠重试解决 - 需要按 schema 级别启停同步,而 wal2json 只能按 slot 级别控制
这时候切到 pglogical 不只是换插件,是换了一套同步语义——它把“数据怎么变”升级成了“数据库状态怎么同步”,代价是多一层抽象、多一点延迟、多一点配置复杂度。