Flink CDC + Iceberg 实时入湖:MySQL Binlog 到湖仓表完整链路
参考 Flink CDC、Dynamic Iceberg Sink 和实时湖仓资料,整理从 MySQL CDC 到 Iceberg 表的链路设计。
实时入湖不是简单同步表
MySQL 到 Iceberg 的实时入湖链路,核心不是“能同步”,而是更新、删除、DDL、Exactly-once、小文件和查询一致性。日志表 append 相对简单,订单、库存、用户这类业务表必须处理主键更新和删除。
MySQL Binlog -> Flink CDC -> 清洗补字段 -> Iceberg v2 -> Trino/Spark/Doris 查询
| |
| +-- schema evolution / compaction
+-- checkpoint / savepoint / restartMySQL 侧要先检查
binlog_format=ROW,否则无法可靠拿到行级变更。- binlog 保留时间要覆盖任务故障恢复窗口。
- server_id 要统一规划,避免多个 CDC 任务冲突。
- 大表全量阶段要评估数据库压力,必要时限速。
Iceberg 表设计
Iceberg v2 支持 row-level delete,更适合 CDC 更新删除场景。分区不要过细,低流量表按小时分区会制造大量小文件。高频查询按 dt、业务域、状态过滤,就要把这些字段纳入分区或排序设计。
CREATE TABLE lake.ods_order ( id BIGINT, user_id BIGINT, status STRING, amount DECIMAL(18,2), op_ts TIMESTAMP(3), dt STRING, PRIMARY KEY (id) NOT ENFORCED ) PARTITIONED BY (dt) WITH ( 'format-version'='2', 'write.upsert.enabled'='true' );
DDL 和 Schema 演进
真实业务一定会新增字段、修改字段长度、枚举值扩展。建议把源库 DDL、Flink SQL、Iceberg schema、下游查询四件事放到同一个发布流程里。否则源表字段已经有了,湖仓表还是旧结构,下游查到大量 null。
小文件和快照治理
Checkpoint 间隔越短、并行度越高、分区越细,小文件越多。Iceberg 的 metadata、manifest、snapshot 也会增长,影响查询 planning。
CALL catalog.system.rewrite_data_files('lake.ods_order');
CALL catalog.system.rewrite_manifests('lake.ods_order');
CALL catalog.system.expire_snapshots('lake.ods_order', TIMESTAMP '2026-04-01 00:00:00');对账怎么做
入湖后不要只看任务 RUNNING。至少要对账:主键数、金额汇总、删除记录数、最大更新时间、分区行数。CDC 链路的正确性问题往往不是立刻报错,而是悄悄多数据或少数据。
生产环境可以直接套用的总结
如果把这篇内容落到真实项目里,建议至少补齐三类信息:第一是基线数据,包括日均数据量、峰值 QPS、任务耗时、存储大小和失败频率;第二是关键配置,包括并行度、分区数、TTL、超时时间、批大小、索引字段;第三是验证结果,包括上线前后耗时对比、资源消耗对比、核心指标对账和异常回滚记录。
写技术博客时也可以按这个顺序组织:先讲业务背景,再讲为什么原方案不稳,然后贴出关键配置或 SQL,最后用对比数据说明优化是否有效。这样文章不会空,也不会像模板填空。
延伸阅读和落地建议
本文按公开技术资料和生产经验重新整理,没有复制原文。真正落地到你的环境时,建议补充:集群版本、资源规格、任务截图、SQL 执行计划、核心监控曲线、上线前后对比数据。这样文章会更像真实生产复盘,也更适合长期维护。