4. 元数据采集原理:从数据库到数据目录的“第一公里”

元数据采集,说白了就是给数据目录“喂数据”的过程。没有这一步,后面所有的血缘分析、数据地图、影响分析都是空中楼阁。我做了这么多年数据治理,见过太多团队在采集阶段就栽了跟头——要么采不全,要么采不准,要么把源系统搞挂了。

这一章,我们就来聊聊元数据采集的三种主流方式,以及我踩过的那些坑。

4.1 三种主流采集方式

目前业界常用的元数据采集方式,归纳起来就三种:JDBC直连、日志解析、API调用。每种方式都有它的适用场景,没有银弹。

采集方式 原理 典型工具 适合场景
JDBC 通过数据库驱动直连,查询系统表/信息模式 Apache Atlas、DataHub 关系型数据库、数据仓库
日志解析 监听数据库或计算引擎的审计日志、执行日志 Debezium、Flume 实时采集、变更捕获
API 调用数据源或平台提供的开放接口 Snowflake、Tableau REST API SaaS平台、云服务

4.2 JDBC采集:最传统,也最稳定

JDBC采集是我个人用得最多的方式。原理很简单:通过数据库的JDBC驱动,连接到目标库,然后查询系统表或INFORMATION_SCHEMA。

举个例子,从MySQL采集表结构:

SELECT 
    TABLE_NAME, 
    COLUMN_NAME, 
    DATA_TYPE, 
    IS_NULLABLE, 
    COLUMN_COMMENT
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_SCHEMA = 'your_database'
ORDER BY TABLE_NAME, ORDINAL_POSITION;

这段SQL能拿到所有表的字段名、类型、是否可空、注释。嗯,这是最基础的元数据。

但JDBC有个大问题——性能压力。我曾经在一个项目里,直接在生产库上跑全量采集,结果把主库的CPU打到了90%。从那以后,我定了个规矩:JDBC采集必须走只读从库,而且采集时间要避开业务高峰期。

⚠️ 避坑指南: 我曾经在凌晨2点跑全量采集,以为没人用就没事。结果那个库是跨时区的,人家那边正是业务高峰。后来我学乖了——采集前先跟DBA确认窗口,并且加上限速参数。

4.3 日志解析:实时性的利器

JDBC采集有个硬伤——它是定时轮询的。如果你需要实时感知表结构变化、数据流动,就得靠日志解析了。

日志解析的原理是:数据库或计算引擎在执行SQL时,会记录审计日志或执行日志。我们通过监听这些日志,解析出元数据变更事件。

比如MySQL的binlog,记录了所有DDL和DML操作。用Debezium这样的工具,可以实时捕获到:

# 一个典型的binlog事件
{
  "type": "ALTER TABLE",
  "table": "orders",
  "timestamp": 1700000000,
  "columns": [
    {"name": "id", "type": "bigint", "change": "unchanged"},
    {"name": "status", "type": "varchar(20)", "change": "modified"},
    {"name": "created_at", "type": "timestamp", "change": "added"}
  ]
}

你想想看,如果靠JDBC轮询,可能要等5分钟甚至1小时才能发现这个变更。但日志解析可以在秒级内感知到。

💡 个人经验: 日志解析虽然实时性好,但解析逻辑很复杂。不同数据库的日志格式不一样,同一个数据库的不同版本也可能有差异。我建议先用现成的框架(如Debezium、Canal),不要自己从头写解析器。

4.4 API采集:云时代的标配

现在越来越多的数据源跑在云上,比如Snowflake、Redshift、Tableau。这些平台通常不提供JDBC直连系统表的权限,而是通过REST API暴露元数据。

API采集的好处是安全可控——平台方帮你封装好了,你只需要调用接口就行。但坏处也很明显:受限于API的返回字段,有些你想要的元数据可能拿不到。

举个例子,从Snowflake采集表信息:

-- Snowflake的INFORMATION_SCHEMA也可以通过JDBC查
-- 但更推荐用它的ACCOUNT_USAGE视图
SELECT 
    TABLE_NAME,
    COLUMN_NAME,
    DATA_TYPE,
    IS_NULLABLE
FROM SNOWFLAKE.ACCOUNT_USAGE.COLUMNS
WHERE TABLE_CATALOG = 'MY_DB';

但如果你用的是Tableau Server,就得走REST API了:

GET /api/3.10/sites/{siteId}/workbooks
Authorization: Bearer {}

返回的JSON里包含了数据源连接信息、字段映射等。嗯,这里要注意——API通常有频率限制,我见过有人一次性拉取几千个工作簿,结果被限流了,整个采集任务卡死。

4.5 采集的三大挑战

说完了方式,我们来聊聊挑战。这些坑,我基本都踩过。

4.5.1 挑战一:性能与安全

采集任务本质上是在“读”源系统。但如果读得太猛,就会影响源系统的写性能。尤其是JDBC方式,一个全量扫描可能把数据库的缓冲池打穿。

我的建议是:

  • 增量采集优先:只采集变更的部分,不要每次都全量
  • 限流与熔断:设置采集线程数、查询超时时间
  • 走从库:不要直连主库

4.5.2 挑战二:元数据格式不统一

不同数据源的元数据模型千差万别。MySQL的字段类型叫varchar,Oracle叫varchar2,Hive叫string。你采集回来之后,必须做归一化。

我曾经维护过一个采集框架,里面维护了20多种数据源的字段类型映射表。每次新增一个数据源,都要手动加映射。后来我改用抽象元数据模型,把类型归类为“字符串”、“数值”、“时间”等大类,才解决了这个问题。

4.5.3 挑战三:血缘信息的缺失

很多数据源本身不记录字段级别的血缘。比如你从MySQL采集表结构,只能知道“有什么字段”,但不知道“这个字段是从哪里来的”。

要解决这个问题,通常需要结合SQL解析。从ETL脚本、视图定义、查询日志中解析出字段的上下游关系。这部分我们会在后面的章节详细讲。

4.6 最佳实践:一个可落地的采集架构

说了这么多,我们来画一张图,看看一个成熟的元数据采集系统长什么样。

元数据采集架构图 数据源层 MySQL / Oracle Hive / Spark Snowflake / Redshift Tableau / PowerBI 采集适配层 JDBC 采集器 日志解析器 API 采集器 SQL 解析器 元数据处理层 元数据归一化 → 类型映射 → 去重 → 血缘关联 元数据存储层 图数据库 (Neo4j) 搜索引擎 (Elasticsearch) 应用层 数据目录 / 血缘分析 / 影响分析

这张图展示了一个典型的采集架构。从上到下分四层:数据源层、采集适配层、元数据处理层、存储层。每一层各司其职,层与层之间通过标准接口解耦。

我个人习惯在采集适配层加一个“采集任务调度器”,统一管理所有采集任务的频率、并发度、重试策略。这样即使某个采集器挂了,也不会影响其他采集任务。

📌 核心要点:
  • JDBC适合批量、定时采集,但要注意性能和安全
  • 日志解析适合实时采集,但解析逻辑复杂
  • API采集适合云平台,但受限于接口能力
  • 无论哪种方式,归一化和增量采集都是必须做的