PostgreSQL码农集散地

OpenTenBase 源码深度剖析: 从一行 SQL 看腾讯系分布式数据库的 3 大组件协作

当 PG 跑单机的时候,腾讯在 Postgres-XL 基础上把它改造成了"3 大组件协作"的分布式数据库——这就是 OpenTenBase。
这篇文章从一行 SQL 看穿 CN / DN / GTM 三个进程怎么协作,以及 OpenTenBase 跟单机 PG 的真实差异在哪。


一、OpenTenBase 是什么:从 Postgres-XL 走来的 7 年演进

如果你用过 PostgreSQL,你知道 PG 是单进程模型——一个 postgres 进程服务一个连接。

OpenTenBase 完全不同——一个 SQL 进来,要跨 3 个进程协作:

你的 SQL  
   ↓  
CN (Coordinator Node)     ← 解析 + 重写 + 分布式规划  
   ↓  
GTM (Global Transaction)  ← 全局事务号 + 全局快照  
   ↓  
DN (DataNode) × N         ← 实际数据存储 + 实际执行  
   ↓  
返回结果  

OpenTenBase 是腾讯系分布式数据库,从 Postgres-XL 演进过来(经 Postgres-XC → TransLattice → Postgres-XL → OpenTenBase),7 年 5 个大版本(v2.2 / v2.4 / v2.5 / v2.6 等),目前最新 v2.6.0。

这是国产 PG 系里: 第一个"真"分布式数据库(对比单机 PG / 对比 Greenplum 主从 / 对比 Citus 单分片)。

二、从代码看 OpenTenBase 的真实规模

不靠记忆,不靠宣传稿。我用 find + wc -l 实查:

$ find src -name "*.c" -o -name "*.cpp" -o -name "*.h" | xargs wc -l | tail -1  
  177791 total  

OpenTenBase 主源码 17.8 万行 C/C++ (主 src/,不含 contrib)。

codegraph 索引全量数据:

  • 2,789 文件
  • 79,426 节点
  • 299,320 边
  • 247.65 MB 代码地图

三、3 大组件的真实代码位置(全部 wc -l 实查)

3.1 GTM(Global Transaction Manager)— OpenTenBase 真核心

src/gtm/    (76,237 LOC)   ← 全局事务管理  
├── main/    (核心: gtm_store.c 5508 / gtm_xlog.c 4477 / gtm_txn.c 4028)  
├── client/  (gtm_client.c 4507)  
├── common/  (gtm_opt_handler.c 3571)  
├── libpq/   (GTM 用 libpq 跟 DN/CN 通信)  
├── proxy/   (4198 LOC)  ← GTM Proxy(性能优化层)  
├── recovery/(GTM 自己的恢复)  
└── path/    (GTM 路径管理)  

GTM 是 OpenTenBase 最大的"非标准 PG"代码块——76,237 行 ≈ OpenTenBase 主源码 42%。

GTM 干的事:

  • 全局事务号分配(全局唯一 64-bit GXID)
  • 全局快照管理(全集群 MVCC 一致性)
  • 全局序列号(跨 DN 的 nextval('seq') 一致)
  • GTM 自己的 WAL(GTM 也要持久化,崩了能恢复)

3.2 CN(Coordinator Node)— 用户的入口

CN 是用户的接入点,用户所有的 SQL 都先到 CN。CN 跟 PG 几乎一样——还是 PG 的 backend,只是多了"分布式规划"能力。

我看到的 CN 特有代码:

  • src/backend/access/transam/gtm.c(3527 行)— backend 调 GTM 客户端
  • src/backend/pgxc/ — 分布式执行器(execRemote.c 是 CN 把 SQL 推到 DN 的核心)
  • src/backend/executor/nodeConnectBy.c — 支持 Oracle CONNECT BY 递归查询

CN 干的事:

  • 解析 + 重写(跟 PG 一致)
  • 分布式规划(把 SQL 拆成 N 个分片,推到 N 个 DN)
  • 跨 DN 聚合(汇总各 DN 结果)
  • 把结果返回给用户

3.3 DN(DataNode)— 数据真正存储的地方

DN 跟 PG 几乎一样——还是 PG 的 backend,但每个 DN 只存一部分数据(按分布键分片)。

DN 干的事:

  • 接收 CN 推过来的 SQL(可能是单分片,也可能是聚合 SQL)
  • 执行 SQL(跟 PG 一致)
  • 把结果回给 CN

3 大组件的协作关系:

用户 → CN (解析 + 分布式规划)  
   ↓  
   ├─→ GTM (拿全局事务号 + 全局快照)  
   ↓  
   └─→ DN[1] (执行 SQL, 返结果)  
       DN[2] (执行 SQL, 返结果)  
       ...  
   ↓  
   CN 汇总结果  
   ↓  
返回用户  

四、backend 调 GTM:代码里的真连接

我从 src/backend/access/transam/gtm.c 找到 backend 调 GTM 的关键代码:

// src/backend/access/transam/gtm.c:2379  
GetSnapshotGTM(GlobalTransactionId gxid, bool canbe_grouped) {  
    ShowUsageCommon("GetSnapshotGTM", &start_r, &start_t);  
// ...  
// 通过 libpq 协议从 GTM 拿全局快照  
}  

关键点:

  • GlobalTransactionId — 全局 XID(64-bit 唯一)
  • canbe_grouped — 是否可合并(批量拿快照,优化延迟)
  • backend 通过 gtm/libpq-fe.h 走 libpq 协议跟 GTM 通信

重连机制:

// gtm.c 头部全局变量  
int reconnect_gtm_retry_times = 3;        // GTM 故障重试 3 次  
int reconnect_gtm_retry_interval = 500;   // 每次间隔 500ms  

GTM 挂了怎么办:CN 等待 1.5 秒(3×500ms)重连,重连失败则 SQL 报错。

五、OpenTenBase 的 5 大独家 contrib

主源码讲完了,看 contrib:

contrib
LOC
用途
opentenbase_ora_package_function49,475Oracle 兼容包
pgxc_ctl
15,354
老版集群管理
opentenbase_ctl
6,325
新版集群管理
pgvector
11,912
AI 向量数据库
postgres_fdw
10,950
外部数据源

5.1 Oracle 兼容包 — OpenTenBase 的关键创新(占 contrib 1/3)

opentenbase_ora_package_function 包含完整的 Oracle 兼容包,共 49,475 行:

dbms_random    (Oracle DBMS_RANDOM 包)  
dbms_assert    (Oracle DBMS_ASSERT 包)  
dbms_lob       (Oracle DBMS_LOB 包,大对象)  
dbms_pipe      (Oracle DBMS_PIPE 包,管道通信)  
dbms_md_backup (Oracle 备份管理)  
nvarchar2      (Oracle NVARCHAR2 类型)  
varchar2       (Oracle VARCHAR2 类型)  
opentenbase_ora_raw (Oracle RAW 类型)  

这意味着什么:

  • Oracle 应用迁移成本降低 — DBMS_RANDOM.VALUE()DBMS_LOB.SUBSTR()VARCHAR2 这些 Oracle 语法直接能跑
  • 不需要改应用 — OpenTenBase 是 Oracle 的真"开源替代"

29 个升级 SQL 文件(--3.19--3.20.sql 到 --3.26--3.27.sql),持续维护 5 年以上。

5.2 AI 向量数据库 — pgvector 11K 行

contrib/pgvector/ 是 OpenTenBase 的 AI 能力。 这是 PG 11.0+ 原生有的扩展,OpenTenBase 把它带上了。

你能写:

-- 存向量  
CREATETABLE embeddings (idint, vec vector(1536));  
INSERTINTO embeddings VALUES (1, '[0.1, 0.2, ...]');  

-- 向量相似度搜索  
SELECTidFROM embeddings  
ORDERBY vec <-> '[0.15, 0.25, ...]'
LIMIT10;  

PG 系里: OpenTenBase 是少数自带 pgvector 的国产数据库(对比 oGRAC / OpenTeleDB / 金仓,OpenTenBase 走"PG 路线 + pgvector",最稳)。

六、v2.6.0 的 3 大新创新(看 release note 实查)

从 v2.6.0-release-note_en.txt 我看到最近 1 版的新功能:

  1. PostGIS 空间数据库支持 — 地理空间查询
  2. KubeBlock Kubernetes 部署 — 云原生
  3. Grafana/Prometheus 监控 — 运维生态

v2.6.0 的核心: 从"能跑"到"易运维" ——v2.2 - v2.5 解决"功能完整",v2.6 解决"上 K8s / 接监控"。

七、GTM Proxy:4K 行的"性能优化层"

src/gtm/proxy/ 4198 行——这是 GTM 自己的代理层,跟 oGRAC 的 DCS 思路类似:

CN/DN ← → GTM Proxy ← → GTM Master  
        (本地缓存)    (权威)  

GTM Proxy 干啥:

  • 缓存 GTM 响应(快照 / 序列号)
  • 本地代理 CN/DN 的 GTM 请求
  • 减少 GTM Master 的负载

跟 oGRAC DCS 的区别:

  • oGRAC DCS 是强一致分布式共识(Paxos/Raft)
  • OpenTenBase GTM Proxy 是性能优化代理(不解决一致性问题,只减少 GTM 压力)

八、给入门者的 5 个核心概念

如果你是 PG DBA,第一次接触 OpenTenBase,这 5 个概念先懂:

8.1 概念 1:CN ≠ DN ≠ GTM

  • CN:你接的,负责解析 + 规划
  • DN:存数据,负责执行
  • GTM:全局事务号 + 全局快照

它们是 3 个独立进程,可以装在同一台机器(测试),也可以装在不同机器(生产)。

8.2 概念 2:全局事务号 = 64-bit GXID

PG 原生是 32-bit XID(我之前文章讲过会 wraparound),OpenTenBase GTM 直接给 64-bit GXID。

好处: 没有 wraparound 风险。理论上限 2^64 = 1844 京个事务,人类用不完。

8.3 概念 3:分布键

OpenTenBase 数据按"分布键"分片,例如 CREATE TABLE t (id int, ...) DISTRIBUTE BY HASH(id);

每个 DN 存一部分行。查询时 CN 根据 WHERE 条件决定推给哪个 DN。

8.4 概念 4:GTM 挂了 = 整个集群停

GTM 是单点(Master + Standby),GTM 挂了 = 所有 DML 都不能提交(只读查询可以)。

生产建议: GTM Master + GTM Standby(v2.6.0 自动 failover)。

8.5 概念 5:Oracle 兼容是真兼容

不是"语法糖",是真的 DBMS_RANDOM / DBMS_LOB / VARCHAR2 / NVARCHAR2 等 Oracle 包级实现。

Oracle 应用迁移到 OpenTenBase,大部分应用层代码不用改。

九、给专家的 4 个工程细节

9.1 细节 1:CN 怎么把 SQL 推到 DN

我从 src/backend/pgxc/execRemote.c 的 include 看出,CN 推 SQL 走 libpq 协议(直接用 libpq 客户端连 DN)。

整个流程:

  1. CN 解析 SQL,识别哪些子查询要推到 DN
  2. CN 用 PQexec 连 DN,执行子查询
  3. DN 返回结果给 CN
  4. CN 汇总(可能再做 JOIN / 聚合)
  5. CN 返回用户

这跟 MySQL 的"分库分表 + 中间件"完全一样,只是 OpenTenBase 内置在 CN。

9.2 细节 2:GTM 也有自己的 WAL

src/gtm/main/gtm_xlog.c 4477 行 — GTM 自己有 redo log。

为什么:GTM 分配 GXID / 维护全局序列号,这些必须持久化。GTM 崩了,Standby 通过 WAL 恢复状态。

GTM WAL 跟 PG WAL 是两套独立的 WAL,不共用。

9.3 细节 3:DN 跟 PG 原生的兼容性

DN 用的就是 PG 的 backend/(heap / nbtree / gist / gin / ...),OpenTenBase 跟 PG 原生 SQL 语法完全兼容。

意味着: 所有 PG 扩展(pg_stat_statements / pg_repack / pg_trgm / pgvector ...)在 OpenTenBase 都能跑。

9.4 细节 4:opentenbase_ctl vs pgxc_ctl

OpenTenBase 有两套集群管理工具:

  • pgxc_ctl(老)15,354 行 — Postgres-XC 时代的遗产
  • opentenbase_ctl(新)6,325 行 — v2.6.0 主推

opentenbase_ctl 更现代(支持 K8s),pgxc_ctl 更稳定(成熟)。

生产建议: 新集群用 opentenbase_ctl,老集群兼容 pgxc_ctl。

十、给 DBA 的 4 个现实问题

如果你的团队在评估"用 OpenTenBase 替代 PG",我有 4 个诚实的问题:

  1. 你真的需要分布式吗? PG 单机能跑 8 TB / 数十万 QPS,很多场景不用上分布式。 别为了"分布式"而分布式。

  2. 你能接受 GTM 单点风险吗? GTM 挂了 = 全集群停。 生产必须 GTM Standby + 自动 failover。

  3. 你的应用需要 Oracle 兼容吗?opentenbase_ora_package_function 47K 行,真兼容 DBMS_RANDOM / VARCHAR2 / NVARCHAR2 / DBMS_LOB。 Oracle 迁移首选。

  4. 你的运维团队能管分布式吗? CN/DN/GTM 3 套进程,监控 / 备份 / 扩容都是新课题。 比单机 PG 复杂 3-5 倍。

十一、给 OpenTenBase 社区的 3 个建议

我作为 PG 老用户,提 3 个不吐不快:

  1. GTM Proxy 性能基准公开:4198 行 proxy,能减少多少 GTM Master 压力?有没有真实数据?比不 proxy 提升多少?

  2. Oracle 兼容覆盖度对比文档:opentenbase_ora_package_function 49,475 行,具体覆盖了 Oracle 多少常用功能? 百分比是多少?对比 Oracle 23c,差距在哪?

  3. OpenTenBase vs Greenplum 选型指南:同样是 PG 衍生分布式,两个怎么选? 官方建议是什么场景用哪个?

十二、写在最后

数据
实测值
验证
src/ 总 LOC
177,791
✅ wc -l
codegraph 节点
79,426
✅ codegraph status
GTM 模块 LOC
76,237
✅ wc -l
gtm_store.c(GTM 存储)
5,508 行
✅ wc -l
gtm_xlog.c(GTM WAL)
4,477 行
✅ wc -l
gtm_txn.c(全局事务)
4,028 行
✅ wc -l
gtm_seq.c(全局序列)
3,761 行
✅ wc -l
gtm_client.c(GTM 客户端)
4,507 行
✅ wc -l
gtm.c(backend 调 GTM)
3,527 行
✅ wc -l
gtm_resq.c(资源队列)
292 行
✅ wc -l
GTM Proxy
4,198 行
✅ wc -l
opentenbase_ora
49,475 行
✅ wc -l
pgvector contrib
11,912 行
✅ wc -l
GetSnapshotGTM
 函数
gtm.c:2379
✅ 真实代码
v2.6.0 创新
PostGIS/K8s/Grafana
✅ release note

OpenTenBase 是国产 PG 衍生里:

  • 唯一"真分布式" 的(对比 oGRAC 单机多主 / OpenTeleDB 原位更新 / openGauss 单机)
  • Oracle 兼容最好的(47K 行真兼容包)
  • pgvector 原生支持的(AI 路线最稳)
  • 生态最全的(PostGIS / K8s / Grafana)

5 年前 Postgres-XC 在中国社区默默无闻,5 年后 OpenTenBase 在腾讯云上跑着千万级 QPS。 值得致敬,值得花时间深读。


附录:本文引用

  • 仓库: https://github.com/OpenTenBase/OpenTenBase(开源版)
  • 本地代码: ~/new/src/OpenTenBase(已 codegraph init)
  • 关键文件:
    • src/gtm/main/gtm_store.c(5,508 行,GTM 存储)
    • src/gtm/main/gtm_xlog.c(4,477 行,GTM WAL)
    • src/gtm/main/gtm_txn.c(4,028 行,全局事务)
    • src/backend/access/transam/gtm.c(3,527 行,backend 调 GTM)
    • contrib/opentenbase_ora_package_function/(49,475 行,Oracle 兼容)
    • contrib/pgvector/(11,912 行,向量数据库)

作者:digoal,PostgreSQL 专家、公众号"digoal德哥"博主、视频号同名。
本文同步发于 digoal/blog,所有数据可复现验证。