Debezium JDBC Connector开启New Record State Extraction后DELETE失效
问题场景
开启**New Record State Extraction(记录解包)**后,Debezium JDBC Connector的DELETE功能无法正常工作。测试环境如下:
- Debezium版本:
debezium/connect:2.6.0.Final - 源数据库:MySQL 8.2.0
- 目标数据库:PostgreSQL 16.2
- 同步模式:MySQL→PostgreSQL CDC
根据官方文档说明:
New Record State Extraction
数据库DELETE操作会生成两条Kafka记录:
- 包含
"op": "d"、before行数据及其他字段的记录;- 与被删除行键值相同、值为null的墓碑记录(用于Kafka日志压缩清理)。
可通过事件扁平化SMT配置保留before行数据记录,支持两种方式:
- 仅保留
"value": "null"字段;- 在before字段的键值对基础上添加
"__deleted": "true"条目作为value字段。
JDBC Sink删除模式
Debezium JDBC Sink Connector可消费DELETE或墓碑事件删除目标库行,默认未启用。需显式设置
delete.enabled=true,且primary.key.fields不能设为none(删除操作依赖主键映射)。
理论上,当JDBC Sink配置delete.enabled=true,同时记录解包设置transforms.unwrap.drop.tombstones=false、transforms.unwrap.delete.handling.mode=none时,DELETE操作应正常执行,但实际测试中功能失效。
已排查确认:
- 未开启unwrap转换时,DELETE功能正常;
- 开启/未开启unwrap两种场景下,Kafka主题中均存在墓碑记录。
可能的问题原因
1. Unwrap转换后的记录格式不被JDBC Sink正确识别
当设置transforms.unwrap.delete.handling.mode=none时,unwrap SMT会保留原始的两条删除相关记录(带"op":"d"的记录+墓碑记录)。但JDBC Sink触发删除仅依赖墓碑记录,且需要从墓碑记录的key中解析主键(因为墓碑记录的value为null)。如果unwrap转换改变了key的结构(比如主键字段名称、嵌套层级变化),JDBC Sink无法正确提取主键,就会导致删除失败。
2. 版本兼容性Bug
Debezium 2.6.0.Final存在unwrap SMT与JDBC Sink配合处理删除事件的兼容性问题。在后续版本(如2.7.0+)中,官方修复了部分CDC同步中的删除逻辑缺陷,建议升级Debezium版本验证是否解决问题。
3. 配置细节遗漏
- 检查
primary.key.fields配置是否准确匹配目标表的主键字段,确保开启unwrap后,主键字段的名称、数据类型与目标表完全一致; - 确认
transforms.unwrap.type是否正确设置为io.debezium.transforms.ExtractNewRecordState,避免其他SMT干扰记录结构; - 排查是否有额外的转换规则(如字段重命名、类型转换)修改了主键字段,导致JDBC Sink无法关联目标表主键。
4. 墓碑记录的主键解析异常
直接查看Kafka中墓碑记录的key内容,确认其结构是否符合JDBC Sink的预期。比如原始CDC记录的key是包含主键的扁平结构体,unwrap后是否变成了嵌套结构,或者主键字段被意外修改,导致JDBC Sink无法正确识别。
内容的提问来源于stack exchange,提问作者Hyuck

