项目中有用到Flink Oracle CDC,下游系统反馈偶有发生data loss的问题,开始我们没有多想,一直误以为是我们后续处理流程导致,通过debezium提供increment snapshot功能修复丢失的数据。后来发现社区也有说到同样的问题,这这才开始紧张了~~
经排查,以及与网友讨论发现确实会存在下面两种情况会发生数据丢失:
1)save point 部分数据回滚,导致一部分数据丢失
2)logminer后事物数据提交,判断数据是否已提交逻辑问题(网友测试发现)
针对这2种情况具体分析如下:
一:savepoint 部分数据回滚,数据丢失。
1)执行sql如下:同一条记录更新多次,回滚了部分更新,预期的结果是字段REORDER_MULTIPLE=6, 7与8的更新都应该回滚。
2)对应log 日志数据如下:
每条记录的更新都会有一条记录,更新(6,7,8)三条记录,对应三条 ROLBACK=0的记录 ;
回滚了几条数据,也会有几条记录,回滚(7,8)两条记录,对应两条 ROLBACK=1的记录
回滚的记录的OPERATION_CODE是与要回滚的记录一样,这个例子是更新对应code是UPDATE(3), 则回滚的记录的code也是UPDATE(3)。
3) 回滚逻辑
回滚的记录的OPERATION_CODE是与要回滚的记录一样,这个例子是更新对应code是UPDATE(3), 则回滚的记录的code也是UPDATE(3)。
4)问题代码
io.debezium.connector.oracle.logminer.TransactionalBuffer
同一条记录的更新(更新6,7,8)row_id都一样,6,7,8的更新事件都会被移除。不应该移除的更新数据6,也被移除了,导致数据丢失。
修改后代码
二:logminer后事物数据提交,判断数据是否已提交逻辑问题
io.debezium.connector.oracle.logminer.TransactionalBuffer
注释是这么写:
不同的日志事件的scn值是有可能一样的,如果两个commit的scn值一样,这就会导致第二个commit 会被过滤,导致第二个commit对应的变化数据丢失。