Flink CDC Oracle连接器我用了差不多两年,从2.4一直追到3.5.0,整体架构变化很大,踩坑记录攒了一大堆。最近一次最让人头疼的是:用3.5.0同步一张Oracle分区表,任务在全量阶段很正常,到了增量阶段却反复报错,作业一直进入重启循环。我把排查过程完整记录下来,里面包括报错现场、根因定位、以及最终改动的几个参数,希望给遇到同类问题的朋友一条可直接照做的路径。
先说结论:如果你也在用Flink CDC 3.x同步Oracle分区表,麻烦在启动任务前先把这四件事检查掉——表上有没有一个能被增量快照使用的唯一键、分区键是否适合作为chunk-key、Oracle补充日志是否真正开启、以及UNDO_RETENTION是否匹配你任务的活跃时长。这四个点占到了我在生产环境遇到的分区表同步故障的八成以上。
1. 问题背景:3.5.0连接器与Oracle分区表相遇
1.1 3.x版本到底改了什么
很多从2.x升级上来的同学,可能还习惯叫“flink-cdc-connector-oracle”,但在3.5.0里工作方式已经完全不同。3.x把连接器拆分成了更细的模块,默认的同步方式是做增量快照(incremental snapshot),不再像老版本那样依赖Debezium的snapshot+lognminer全量分片方式。它在全量阶段会把一张表切分成多个chunk,然后以chunk为单位做多并行度的数据拉取。
分区表在这里有一个天然的问题:分区表里往往存在大量物理分区,而业务上没有设置主键,或者主键列并不是分区键。增量快照在切分chunk时必须选一个用来排序和断言的键,官方默认行为是“找主键或唯一索引”,找不到就直接报错。分区表属于重灾区,因为DBA一般不会给一张定期清理历史分区的表建主键,主键会被认为影响分区维护效率。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
1.2 我这次同步的是一张什么表
生产环境里有一张订单流水表,按月份做了RANGE分区,分区名类似“PART_202401”“PART_202402”,每个分区大约8000万行,整表超过6亿行。这张表没有主键,但有一个业务唯一索引UK_ORDER_NO(ORDER_NO, BATCH_ID),索引是全局索引还是本地索引呢,不巧的是它是本地索引。
当时为了快速上线,我建连接器时只配置了最基本的连接参数,把希望完全寄托于Flink CDC自己去发现可用键。结果全量阶段确实跑了,但到了增量阶段就开始报错,而且报错信息非常误导人。
1.3 报错现场重现
任务运行大约40分钟后,作业日志开始刷:
code复制Caused by: java.sql.SQLException: ORA-01555: snapshot too old: rollback segment number unknown with name "" too small
紧接着:
code复制Caused by: io.debezium.DebeziumException: Failed to read redo log entries
从表面上看,这纯粹是Oracle的UNDO不够用,导致LogMiner无法读取到足够的回滚数据。但实际深入查下来,UNDO只是压死骆驼的最后一根稻草。真正的问题在于分区表上没有合适的索引,Flink CDC被迫使用低效方式扫描,导致全量与增量切换阶段严重拖慢,LogMiner在读取时跨越了UNDO的保留窗口。
2. 第一波排查:Oracle侧配置
2.1 补充日志不是随便开一下就完事
遇到CDC问题,第一个想查的自然是补充日志。很多文档只说“要开启最小补充日志”,但实际同步时还有一个细节容易被忽略:表级别的主键/唯一键补充日志。
数据库级别执行:
sql复制SELECT SUPPLEMENTAL_LOG_DATA_MIN,
SUPPLEMENTAL_LOG_DATA_PK,
SUPPLEMENTAL_LOG_DATA_UI,
SUPPLEMENTAL_LOG_DATA_ALL
FROM V$DATABASE;
如果MIN为NO,需要:
sql复制ALTER DATABASE ADD SUPPLEMENTAL LOG DATA;
但仅仅开启数据库级别的补充日志还不够。对于没有主键只有唯一索引的表,Debezium/Flink CDC在解析变更前镜像时,必须依赖补充日志里的列数据。如果表上没有任何唯一键或主键的补充日志, LogMiner吐出来的SQL可能不包含完整的前镜像,导致反序列化失败。
我这次查看时,数据库级别MIN
