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— 支持 OracleCONNECT 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:
| opentenbase_ora_package_function | 49,475 | Oracle 兼容包 |
| pgxc_ctl | ||
| opentenbase_ctl | ||
| pgvector | AI 向量数据库 | |
| postgres_fdw |
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 版的新功能:
PostGIS 空间数据库支持 — 地理空间查询 KubeBlock Kubernetes 部署 — 云原生 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)。
整个流程:
CN 解析 SQL,识别哪些子查询要推到 DN CN 用 PQexec连 DN,执行子查询DN 返回结果给 CN CN 汇总(可能再做 JOIN / 聚合) 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 个诚实的问题:
你真的需要分布式吗? PG 单机能跑 8 TB / 数十万 QPS,很多场景不用上分布式。 别为了"分布式"而分布式。
你能接受 GTM 单点风险吗? GTM 挂了 = 全集群停。 生产必须 GTM Standby + 自动 failover。
你的应用需要 Oracle 兼容吗?
opentenbase_ora_package_function47K 行,真兼容 DBMS_RANDOM / VARCHAR2 / NVARCHAR2 / DBMS_LOB。 Oracle 迁移首选。你的运维团队能管分布式吗? CN/DN/GTM 3 套进程,监控 / 备份 / 扩容都是新课题。 比单机 PG 复杂 3-5 倍。
十一、给 OpenTenBase 社区的 3 个建议
我作为 PG 老用户,提 3 个不吐不快:
GTM Proxy 性能基准公开:4198 行 proxy,能减少多少 GTM Master 压力?有没有真实数据?比不 proxy 提升多少?
Oracle 兼容覆盖度对比文档:
opentenbase_ora_package_function49,475 行,具体覆盖了 Oracle 多少常用功能? 百分比是多少?对比 Oracle 23c,差距在哪?OpenTenBase vs Greenplum 选型指南:同样是 PG 衍生分布式,两个怎么选? 官方建议是什么场景用哪个?
十二、写在最后
| 177,791 | ||
| 79,426 | ||
| 76,237 | ||
| 49,475 行 | ||
GetSnapshotGTM | ||
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,所有数据可复现验证。