PostgreSQL 逻辑复制 Stream 执行逻辑源码级拆解:从 reorderbuffer 触发到订阅端落盘回放
本文是「PostgreSQL 逻辑复制源码系列」。定位说明:
本文是「PostgreSQL 逻辑复制源码系列」。定位说明:
本文源码基线:PostgreSQL 18(/Users/growduduan/cwork/postgresql),所有行号可直接 cd 到对应源码目录校对。本文聚焦一条关键链路:从输出插件回调 pgoutputchange 一路追到 HeapTupleSatisfiesVisibility 在何种场景下被触发,并在 SNAPSHOTHISTORICMVCC 分支中如何完成可见性判定。
本文是 reorderbuffer.c 源码深度解析 的姊妹篇:前者讲架构/生命周期/数据结构骨架,本文按 reorderbuffer.c 出现的所有 95 个函数 逐个讲透。每个函数都带 文件:行号 / 原型 / 完整代码 / 逐行解释 / 调用方 / 边界情况。
之前几篇(end-to-end 全流程、LSN 推进全景、snapbuild.c 全函数拆解、SnapBuildFindSnapshot 状态机)虽然覆盖了入口、状态机和 LSN 推进,但对catalog 改动如何从 WAL 一路透传到订阅端的可见性判定这一条核心链路解释得不够细致。本文专门补这一段:
配套源码:~/cwork/postgresql/src/backend/utils/cache/{syscache,catcache,inval}.c(共 5243 行)
配套源码:~/cwork/openGauss-server/(openGauss 2.x / 3.x)涉及文件:access/transam/{xact,cxlog,csnlog,transam,xlog}.cpp、include/c.h、include/access/transam.h、include/access/xact.h、storage/replication/logical/{prot…
配套源码:~/cwork/openGauss-server/src/gausskernel/storage/replication/logical/(openGauss 2.x / 3.x,4250 行并行解码核心代码 + 继承自 PostgreSQL 的逻辑复制框架)
配套源码:src/backend/replication/{walsender.c, slot.c, slotfuncs.c} + src/backend/replication/logical/* + src/include/access/xlogdefs.h
配套源码:~/cwork/postgresql/src/backend/replication/logical/snapbuild.c:1238-1430(193 行)
配套源码:~/cwork/postgresql/src/backend/replication/涉及文件:walsender.c(2146 行的协议入口)、slotfuncs.c(284 行的 SQL 函数)、logical.c(2198 行的解码框架)、slot.c(1300 行的 slot 实现)、snapbuild.c(2076 行的状态机)
配套源码:~/cwork/postgresql/src/backend/replication/(PG 18 主干,30+ 文件、30K+ 行)
配套源码:~/cwork/postgresql/src/backend/replication/logical/snapbuild.c(PG 18 主干,2076 行)
本文是「PostgreSQL 内核机制源码系列」的元文章——它本身不深入某个子系统,而是给出研究所有子系统的学习路径。同系列文章:
本文是「PostgreSQL 逻辑复制源码系列」第 6 篇——前 5 篇把 RUNNING_XACTS 写盘、SnapBuild 状态机、ReorderBuffer 重组、pgoutput 协议、apply worker 入口都拆解过。本文第一次把它们串成一条线。同系列前文:
本文是「PostgreSQL 逻辑复制源码系列」。同系列前文:
本文是「PostgreSQL 扩展系列」列存 / OLAP 篇。同系列前文:cstore_fdw 深度解析、Citus Columnar 深度解析
本文是「PostgreSQL 扩展系列」列存篇。同系列前文:TimescaleDB 深度解析、cstore_fdw 深度解析
本文是「PostgreSQL 扩展系列」列存篇。同系列前文:cstore_fdw 深度解析、Citus 深度解析
本文是「PostgreSQL 扩展系列」列存篇。同系列前文:TimescaleDB 深度解析、Citus 深度解析
本文是「PostgreSQL 扩展系列」备份恢复篇。同系列前文:PostgreSQL 核心特性全景
本文是「PostgreSQL 扩展系列」加密篇。同系列前文:PostgreSQL 核心特性全景
本文是「PostgreSQL 扩展系列」审计合规篇。同系列前文:PostgreSQL 核心特性全景
本文是「PostgreSQL 扩展系列」观测篇。同系列前文:PostgreSQL 核心特性全景
本文是「PostgreSQL 源码系列」项目篇。同系列前文:
想象你正坐在一家只能容纳一桌客人的小餐厅里。厨房只有一个炉子,但每天要接待几十位客人。老板不愿意花大钱雇十个厨师,于是发明了一套"接力"流程:客人坐下前先填一份菜单,写好之后交给厨房;厨房不是一道菜做完再接下一道,而是把今天的菜单攒成一摞,按"出餐顺序"一份一份炒;炒好了用小窗口递出去;客人吃完再喊下一份。整个过程里,菜单会不断被改写(客人加菜)、堆叠(多桌拼桌)、回滚(某桌取消)。
想象一下,PostgreSQL 里有 200 个 backend 同时挤在 shared_buffers 上抢同一个热点 page。某个 backend 在等 WALFlush,另一个在等 LockManager,还有一个在等客户端的下一条 SQL。它们都在睡觉,但都不能用 sleep(1)——一秒后醒来数据可能早被别人改完了。
applyparallelworker.c 表面上是一个 1646 行的文件,但里面同时承载了 两套截然不同的角色:
配套源码:~/cwork/postgresql(基于 PG 18 主干)
配套源码:~/cwork/postgresql(基于 PG 18 主干)
配套源码:~/cwork/postgresql(基于 PG 18 主干)
配套源码:~/cwork/postgresql(基于 PG 18 主干)配套前文:Apply Parallel Worker 运行机制解析
源码基线:PostgreSQL 18(src/backend/replication/logical/{applyparallelworker,worker,launcher}.c)
文档版本:v1.0适配版本:PostgreSQL 18源码基线:src/backend/replication/logical/{worker,applyparallelworker,launcher}.c、src/include/replication/{logicalworker,worker_internal}.h
文档版本:v1.0适配版本:PostgreSQL 18(含社区已合入的并行 Apply 增强补丁)源码基线:src/backend/replication/logical/{worker,applyparallelworker,launcher,tablesync}.c
文档版本:v1.0适配版本:PostgreSQL 18源码基线:src/backend/replication/logical/{worker,applyparallelworker}.c、src/include/replication/worker_internal.h
本文是一份性能分析入门 + 实战指南。前半段讲清楚火焰图和 perf 是什么、怎么用;后半段用 PostgreSQL 逻辑复制的 4 个真实问题,演示怎么用火焰图定位瓶颈。读完你会获得一个完整的"实战方法论"。
本文从 Linux 内核视角讲清楚共享内存 —— 为什么有它、内核是怎么实现的、用户态有哪些 API、主流开源项目怎么用。读者:内核 / 系统 / 后端 / 数据库开发者。
本文基于 PostgreSQL 18 源码(src/backend/storage/ipc/、src/backend/utils/mmgr/),从内核视角讲清楚共享内存是怎么回事 —— 为什么需要它、它分几层、内核开发者怎么用它。
本文是「PostgreSQL 源码系列」内核开发篇。配套源码版本:PostgreSQL 18 dev(~/cwork/postgresql,REL183 之后 77 commit)。同系列前文:
本文是「PostgreSQL 源码系列」并发篇。配套源码版本:PostgreSQL 18 dev(~/cwork/postgresql)。同系列前文:
本文是「PostgreSQL 源码系列」执行器篇。配套源码版本:PostgreSQL 18 dev(~/cwork/postgresql)。同系列前文:
本文是「PostgreSQL 源码系列」压测篇。配套源码版本:PostgreSQL 18 dev(~/cwork/postgresql)。同系列前文:
本文是「PostgreSQL 源码系列」的逻辑复制 worker 模型篇。配套源码版本:PostgreSQL 18 dev(~/cwork/postgresql)。同系列前文:
本文是「PostgreSQL 源码系列」的逻辑复制性能篇。配套源码版本:PostgreSQL 18 dev(~/cwork/postgresql)。同系列前文:
本文是「PostgreSQL 源码系列」的总览篇。配套源码版本:PostgreSQL 18 dev(~/cwork/postgresql)。同系列前文:
本文是「PostgreSQL 系列」的视角篇 · 三。配套源码版本:PostgreSQL 18 dev(~/cwork/postgresql)。同系列前文:
本文是「PostgreSQL 系列」的视角篇 · 二。配套源码版本:PostgreSQL 18 dev(~/cwork/postgresql)。同系列前文:
本文是「PostgreSQL 系列」的视角篇。配套源码版本:PostgreSQL 18 dev(~/cwork/postgresql)。同系列前文:
本文是「PostgreSQL 逻辑复制系列」的第 N 篇,重点不在原理拆解,而在「用一条 docker compose up -d 把 publisher/subscriber 拉起来」。同系列前文:
本文是「PostgreSQL 逻辑复制系列」的第 N 篇。配套源码版本:PostgreSQL 18 dev(~/cwork/postgresql)。同系列前文:
本文是「PostgreSQL 逻辑复制系列」的第 N 篇。配套源码版本:PostgreSQL 18 dev(~/cwork/postgresql)。同系列前文:
本文是「PostgreSQL 逻辑复制系列」的 spill 专题。配套源码版本:PostgreSQL 18 dev(~/cwork/postgresql)。同系列前文:
本文是「PostgreSQL 逻辑复制系列」的延伸篇。配套源码版本:PostgreSQL 18 dev(~/cwork/postgresql)。同系列前文:
本文是「PostgreSQL 逻辑复制系列」的第 N 篇。配套源码版本:PostgreSQL 18 dev(~/cwork/postgresql)。同系列前文:
本文是 PostgreSQL 逻辑复制与分区表:从 publisher 到 partition leaf 的全链路 的深度细化篇。
本文是 PostgreSQL 逻辑复制的 Worker 模型 与 PostgreSQL 逻辑复制与分区表:从 publisher 到 partition leaf 的全链路 的姊妹篇。
本文是 PostgreSQL 逻辑复制与分区表:从 publisher 到 partition leaf 的全链路 的姊妹篇。
本文是 PostgreSQL 分区表:从一行 PARTITION BY 到路由热路径的全链路拆解 的姊妹篇。
本文是 PostgreSQL 分区表:从一行 PARTITION BY 到路由热路径的全链路拆解 的前置文档。那篇深挖内核源码、catalog、relcache、路由算法;这一篇专门讲实战使用——两边的步骤、典型场景、详细差异。
想象你是一家快递公司的调度总监。每天有几百万个包裹要按目的地分拣。一开始你让所有快递员把包裹堆在一张巨大的桌子上,靠肉眼找路线——等找到时客户已经催单催到爆。
本文为 PostgreSQL 官方 Wiki Don't Do This 页面的中文翻译整理。- 原文链接:https://wiki.postgresql.org/wiki/Don%27tDoThis
本文为 Hazel Bachrach 所著 What I Wish Someone Told Me About Postgres 一文的中文翻译整理。
本文为 Dr. Raphael A. Bauer 所写 PostgreSQL for Everything 一文的中文翻译整理。
CREATE SUBSCRIPTION 那一长串 WITH (...) 参数,每个都对应 pg_subscription 系统表里的一列,背后是 apply worker 一段真实的代码分支。
PostgreSQL 启动时申请的 shared_buffers 那一大段内存,其实只是冰山一角。整座数据库的"内存世界"由三层拼起来:
想象一下,你正坐在一家 24 小时营业的自助图书馆里。顾客们进进出出,有人想改书里的一段话,有人想删掉某一页。如果每改一次都要把整本书收回柜台、贴上封条、再发出去,那这家图书馆基本就瘫痪了。
本文介绍如何使用 BenchmarkSQL 对 PostgreSQL 进行 TPC-C 压测,重点覆盖配置、数据装载、运行命令、执行链路、结果分析和常见故障排查。
目标:吃透 PG 的 logical replication 全套机制——logical decoding、ReorderBuffer、output plugin、publication/subscription、initial sync、conflict handling、walsummarizer。这是 PG 实现跨大版本、跨表、跨粒度复制的核心能力。
目标:搞清楚 OLTP 的行存与 OLAP 的列存的本质差异,了解 PG 原生为啥是行存、cstorefdw / parquetfdw / Hydra 怎么实现列存、PG 17/18 列存方向。这是面试常被问、也是存储引擎内核最常被重构的方向之一。
目标:吃透 PG 的 streaming replication 全套机制——wal sender、wal receiver、replication slot、sync vs async、cascade、failover、monitoring。这是读写分离、高可用、灾备的基石。
目标:把 PG 的 crash recovery 单独成章,吃透 redo 全流程、timeline 切换、PITR 的内部细节、partial restore、recovery target 与 promote。这是"内核工程师"与"会用 PG"的关键分水岭,因为很多线上故障都靠它定位。
目标:把前面 9 章没覆盖的访问方法与执行层高级特性收口:其他 access method(hash/gist/gin/spgist/brin)、并行执行、分区、FDW、JIT、logical replication。这一章不要求每项精通,但需要知道“这些都怎么入手”。
目标:吃透 PG 的 Write-Ahead Logging 子系统——XLogRecord 结构、rmgr 注册表、redo/undo、checkpoint、recovery、流复制。这是与 InnoDB redo log 最常被拿来对照的部分。
目标:把 PG 的“事务子系统”吃透:xact 状态机、Snapshot、clog/subtrans、lmgr 的表/页/元组三级锁、lwlock、SSI 实现。这是“资深内核开发”与“会用 PG”的分水岭。
目标:从页面布局到搜索 / 插入 / 分裂 / 删除 / WAL 全流程吃透 PG 的 B-Tree 实现。PG 13+ 引入的 deduplication 是重点。
目标:理解 PostgreSQL 堆表的页面布局、HeapTuple 结构、xmin/xmax/cmin/cmax 语义、HOT 链、pruning、vacuumlazy。这是 PG 与 MySQL InnoDB 在工程上最大的差异点。
目标:掌握 PostgreSQL shared buffer pool 的实现——BufferDesc 元数据、hash 索引、clock-sweep 替换策略、AIO 集成、lock 与 pin 的差别。这一章是“存储引擎内核”最关键的章节。
目标:理解 PG 在“OS 文件系统”和“表/索引页面”之间插的一层抽象(Storage Manager),以及默认实现磁碟版(md.c)。这一层是 PG 与其它 DBMS 在工程上差异最大的一处——比 InnoDB 的 fil_system 还更“裸露”。
目标:从 backend 收到一条 query 字节那一刻起,逐函数跟踪到执行器出口。理解 解析 → 重写 → 优化 → 执行 四阶段的产物(RawStmt / Query / PlannedStmt / PlanState)。
目标:理解“一个客户端连接 = 一个 backend 进程”的进程模型,掌握 postmaster 如何 fork / signal 整个家族,以及每个子进程的工作。
目标:能在 ~/cwork/postgresql 上 30 分钟内编译成功、能 GDB 跟一条 SQL、能用 ctags / cscope 在代码里跳转。
问题原因:逻辑复制同步DDL在sqlserver模式下不支持分区表同步,根本原因为分区表创建依赖于Partition Function 、Partition Scheme,但这两个语句不走PG标准的执行流程(ProcessUtility),无法被捕获。
1.当前产品面向比亚迪现场,现场需要sqlserver模式,当前sqlserver模式下的逻辑复制能力范围边界尚不清楚;(从产品和架构层面出发评估)
{margin: 0;padding: 0;box-sizing: border-box;}body {font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
当前数据库使用babelfish插件(bbf)来支持sqlserver模式,bbf采用双端口的设计:即数据库在启动时会监听多个端口,一般是pg原生的端口和tsql端口,比如5432和1433.
本文档汇总 Babelfish 插件在 SQL Server 模式下使用逻辑复制 DDL 自动同步时的已知限制,并按客户使用影响给出分级和建议做法。
PostgreSQL 的 searchpath 可以设置多个 schema,但其他数据库如 Oracle 的 ALTER SESSION SET CURRENTSCHEMA = ZXF 只能设置一个。这在一条 SQL 包含多个 schema 的场景下,无法进行直接转换。
PostgreSQL 当前内建逻辑复制主要覆盖表级 DML 复制。logical decoding 的本质是从 WAL 中提取持久化变更,转成更高层可理解的变更流;复制槽保证“按源端发生顺序”向客户端提供变化序列。([PostgreSQL][1])
可以,下面我直接给你一版接近 PostgreSQL patch 风格的 LogLogicalDDLMessage() 实现草稿。它的设计核心是:复用 PostgreSQL 现有 generic logical decoding message 的 WAL 记录格式与写入路径。
在初次写入数据的时候,ddl写到了系统表,dml先写入日志,然后apply成数据。当前逻辑复制的原理是根据lsn读取wal日志,将wal日志decode成sql,然后发送目标端。
一个DDL需要多个事务,比如在线建分区;2. 性能问题;(发布性能较低,流式发布)3. 用户接口跟产品确认;(用户接口清单,ddl同步范围),table和others的清单列出;
本文通过实际操作演示 PostgreSQL 15 逻辑复制的完整流程,重点展示:- WAL(Write-Ahead Logging)日志的生成与解析
本文面向需要理解 PostgreSQL 逻辑复制/逻辑解码链路的开发人员,解释 LogLogicalMessage 的定位、内部实现、设计初衷和工程使用方式。
在 PostgreSQL 扩展开发中,DefineCustom*Variable 系列函数用于 注册自定义 GUC(Grand Unified Configuration)参数。
pglogical.so是pglogical中的数据库扩展(extension),负责管理复制拓扑、节点、replication set、apply worker 等控制逻辑。
逻辑解码(Logical Decoding)是 PostgreSQL(及其扩展版本)提供的一套机制,用来将 WAL(物理日志)中的数据修改恢复成“逻辑级别”的变更事件: