SQL pglogical / pgoutput / wal2json 的逻辑复制输出插件性能对比

1次阅读

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

SQL pglogical / pgoutput / wal2json 的逻辑复制输出插件性能对比

pglogical 和 pgoutput 哪个复制延迟更低

pgoutput 原生协议直接走 WAL 解析 + 流式发送,不经过 sql 层,延迟天然比 pglogical 低 50–80ms(实测 1k TPS 场景下,pgoutput 端到端延迟常在 20ms 内,pglogical 多一层逻辑解析和冲突处理,通常 80–150ms)。但这个优势只在“纯追加、无 DDL、无跨库映射”的简单拓扑里成立。

容易踩的坑:

  • pgoutput 是 postgresql 内置协议,只能用于 postgrespostgres 的复制,不支持写入 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-transactionfalse 关闭事务头包装,省掉一层嵌套
  • 禁用旧值:启动 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 不只是换插件,是换了一套同步语义——它把“数据怎么变”升级成了“数据库状态怎么同步”,代价是多一层抽象、多一点延迟、多一点配置复杂度。

text=ZqhQzanResources