2、血缘捕获技术选型:基于日志的捕获(CDC)、基于解析器的捕获(SQL Parser)、基于代理的捕获(Agent)

选型这件事,说白了就是「没有银弹」。

我在做数据治理的头两年,总想着找一个万能方案,能搞定所有场景。后来被现实教育了——不同的数据源、不同的业务容忍度、不同的团队能力,决定了你该用哪把刀。今天咱们就把这三把刀摆在桌上,一个一个拆开看。

2.1 基于日志的捕获(CDC)

CDC 的全称是 Change Data Capture,翻译过来就是「变更数据捕获」。它的核心思路很简单:不去碰业务表,而是去读数据库的日志文件。

你想想看,数据库每做一次 INSERT、UPDATE、DELETE,都会写日志。MySQL 有 binlog,PostgreSQL 有 WAL,Oracle 有 Redo Log。CDC 就是蹲在日志文件旁边,一条一条地读,然后把变更事件推出去。

核心优势:对业务系统零侵入。不需要改表结构,不需要加触发器,不需要业务方配合。我见过太多因为加触发器导致数据库性能抖动的案例了——CDC 完全避免了这个问题。

我在项目中遇到过一件事:某金融客户的核心交易系统,DBA 死活不让碰表结构,连加个索引都要审批两周。最后我们用 Debezium 监听 MySQL binlog,把变更流实时推到 Kafka,血缘系统直接从 Kafka 消费。整个过程没动业务一行代码。

对比维度 CDC 方案 说明
延迟 毫秒级 日志写入后立即捕获
侵入性 无 只读日志,不碰业务表
支持的数据源 MySQL、PostgreSQL、Oracle、SQL Server 等 主流关系型数据库基本都支持
捕获内容 完整的前后镜像 能拿到变更前后的整行数据
运维成本 中等 需要维护 CDC 组件的高可用

我的建议:如果你的业务数据库是 MySQL 或 PostgreSQL,并且你能接受引入 Kafka 或 Pulsar 这类消息中间件,CDC 是首选。工具方面,Debezium 是目前最成熟的,社区活跃,坑也填得差不多了。

2.2 基于解析器的捕获(SQL Parser)

SQL Parser 的思路跟 CDC 完全不一样。它不碰日志,而是去解析 SQL 语句本身。

举个例子:你在数据平台上跑了一条 INSERT INTO dws_sales SELECT ... FROM ods_order JOIN dim_product,SQL Parser 会把这条 SQL 拆成语法树,然后告诉你:目标表是 dws_sales,源表是 ods_order 和 dim_product,字段映射关系是什么。

说白了,它是在「静态分析」SQL 的血缘关系。不需要实时监听,不需要日志权限,只要拿到 SQL 文本就能干活。

注意:SQL Parser 有一个天然的限制——它只能分析「你能拿到」的 SQL。如果 SQL 被封装在存储过程里,或者通过 ORM 框架动态生成,解析难度会急剧上升。我曾经在一个项目里被 MyBatis 的动态 SQL 折磨了整整两周,最后不得不放弃全量解析,只处理显式的 INSERT … SELECT 语句。

SQL Parser 的典型应用场景是离线数仓的血缘分析。比如 Hive、Spark SQL、Flink SQL 这些引擎,执行计划是可以捕获的,SQL 文本也是可以归档的。你只需要把 SQL 收集起来,定时跑一遍解析,就能构建出完整的血缘链路。

对比维度 SQL Parser 方案 说明
延迟 分钟级到小时级 取决于 SQL 采集周期
侵入性 低 只需要 SQL 文本,不需要改系统
支持的数据源 Hive、Spark、Flink、Presto、Doris 等 主要面向 OLAP 和批处理引擎
捕获内容 表级和字段级血缘 能解析出字段级别的映射关系
运维成本 低 通常是一个离线任务

避坑指南:我曾经天真地以为所有 SQL 都能被完美解析。直到遇到 Oracle 的存储过程里嵌套了动态 SQL,里面还用了 EXECUTE IMMEDIATE……嗯,那次的解析覆盖率只有 60%。所以我的建议是:SQL Parser 适合做「离线血缘的基线构建」,不适合做「实时血缘的精确捕获」。

2.3 基于代理的捕获(Agent)

Agent 方案是最「重」的,也是最灵活的。

它的做法是在数据源或计算引擎上部署一个代理程序。这个代理可以是一个 Java Agent(比如在 JVM 里做字节码增强),也可以是一个 Sidecar 容器(比如在 Kubernetes 里跟任务跑在一起),甚至可以是一个 Hook 脚本(比如在 Airflow 的 DAG 执行前后触发)。

代理能做的事情比前两种多得多:它不仅能捕获 SQL,还能捕获执行上下文、运行时变量、数据采样结果,甚至能拦截网络请求。代价就是——你得维护这个代理,而且它可能会影响原系统的性能。

适用场景:当 CDC 拿不到日志权限,SQL Parser 又解析不了动态 SQL 的时候,Agent 就是最后的底牌。我见过一些大厂的自研数据平台,直接在 Spark Driver 里埋点,通过 Agent 把每个 Stage 的输入输出表都上报到血缘中心。

对比维度 Agent 方案 说明
延迟 秒级到分钟级 取决于 Agent 上报策略
侵入性 高 需要部署和运维 Agent
支持的数据源 自定义,几乎无限制 只要能写 Agent 就能接入
捕获内容 最丰富 SQL + 上下文 + 运行时信息
运维成本 高 Agent 版本管理、兼容性、性能监控

我的教训:Agent 方案最怕的是「版本碎片化」。我曾经维护过一个自研 Agent,因为业务方升级了 Spark 版本,Agent 没跟上,结果血缘数据断了整整一周。从那以后,我要求所有 Agent 必须跟计算引擎的版本做绑定发布,每次引擎升级,Agent 必须同步验证。

2.4 三种方案的对比与选型建议

好了,三把刀都摆出来了。怎么选?我个人的经验是:

  • 实时交易系统、OLTP 数据库 → 优先 CDC。零侵入,低延迟,成熟度高。
  • 离线数仓、ETL 任务、OLAP 引擎 → 优先 SQL Parser。成本低,覆盖广,够用。
  • 自研平台、复杂执行链路、需要深度上下文 → 考虑 Agent。灵活但重,要有运维兜底。

当然,实际项目中往往是混合使用。比如我最近在做的项目:MySQL 的实时变更用 CDC,Hive 的离线任务用 SQL Parser,Flink 的实时计算任务用 Agent 做运行时埋点。三种方案各管一摊,互不干扰。

血缘捕获技术选型全景图 数据源 / 计算引擎 CDC 日志捕获 SQL Parser 解析 Agent 代理捕获 Debezium / Canal Maxwell / DMS binlog / WAL / Redo Log Druid SQL Parser Antlr / Calcite 语法树 + 字段映射 Java Agent / Sidecar 字节码增强 / Hook 运行时上下文捕获 实时变更事件流 离线血缘关系 深度上下文血缘 选型建议:实时 OLTP → CDC | 离线数仓 → SQL Parser | 自研平台 → Agent | 实际项目通常混合使用

最后说一句:选型不是一锤子买卖。随着业务发展,你的血缘捕获方案也需要动态调整。比如一开始用 SQL Parser 就够了,后来业务要求实时影响分析,那就得引入 CDC。保持架构的扩展性,比一开始选对方案更重要。