Ticdc canal-json 格式中的 binary 数据如何解析

【 TiDB 使用环境】测试
【 TiDB 版本】 v7.1.2
【复现路径】做过哪些操作出现的问题

【遇到的问题:问题现象及影响】
通过 ticdc 将数据导入到 kafka 中,再从 kafka 中将原始数据直接导入到 hdfs,发现 binary 格式的数据有乱码。想了解一下如果要将canal-json binary 数据通过 kafka 同步出去应该如何解析或者有方式配置 binary 格式的数据在 canal-json 中用 base64编码吗?

【资源配置】
【附件:截图/日志/监控】
建表语句:
CREATE TABLE all_field_test (
id bigint(20) NOT NULL,
col1 datetime DEFAULT NULL,
col2 datetime(6) DEFAULT NULL,
col3 time DEFAULT NULL,
col4 decimal(20,5) DEFAULT NULL,
col5 timestamp(6) NULL DEFAULT NULL,
col6 date DEFAULT NULL,
col7 year(4) DEFAULT NULL,
col8 binary(16) DEFAULT NULL,
col9 blob DEFAULT NULL,
col10 smallint(6) DEFAULT NULL,
col11 float DEFAULT NULL,
col12 double DEFAULT NULL,
PRIMARY KEY (id) /*T![clustered_index] CLUSTERED */
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin

数据库中的测试数据:

canal-json text 的原始数据: col8 和 col9 中的数据有乱码,下游收到后应该如何解析呢?
{
“id”:0,
“database”:“test”,
“table”:“all_field_test”,
“pkNames”:[
“id”
],
“isDdl”:false,
“type”:“UPDATE”,
“es”:1700623634900,
“ts”:1700623635892,
“sql”:“”,
“sqlType”:{
“id”:-5,
“col1”:93,
“col2”:93,
“col3”:92,
“col4”:3,
“col5”:93,
“col6”:91,
“col7”:12,
“col8”:2004,
“col9”:2004,
“col10”:5,
“col11”:7,
“col12”:8
},
“mysqlType”:{
“col8”:“binary”,
“col12”:“double”,
“col1”:“datetime”,
“col2”:“datetime”,
“col3”:“time”,
“col6”:“date”,
“col7”:“year”,
“col11”:“float”,
“id”:“bigint”,
“col4”:“decimal”,
“col5”:“timestamp”,
“col9”:“blob”,
“col10”:“smallint”
},
“old”:[
{
“id”:“4”,
“col1”:“2023-11-21 11:48:13”,
“col2”:“2023-11-21 11:48:16.000000”,
“col3”:“02:10:00”,
“col4”:“12345.67890”,
“col5”:“2023-11-21 11:48:40.000000”,
“col6”:“2023-11-21”,
“col7”:“2023”,
“col8”:“00\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000”,
“col9”:“abcd”,
“col10”:“2”,
“col11”:“3.14”,
“col12”:“6.28”
}
],
“data”:[
{
“id”:“4”,
“col1”:“2023-11-21 11:48:13”,
“col2”:“2023-11-22 11:48:16.000000”,
“col3”:“02:10:00”,
“col4”:“12345.67890”,
“col5”:“2023-11-21 11:48:40.000000”,
“col6”:“2023-11-21”,
“col7”:“2023”,
“col8”:“00\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000”,
“col9”:“abcd”,
“col10”:“2”,
“col11”:“3.14”,
“col12”:“6.28”
}
],
“_tidb”:{
“commitTs”:445808282147225603
}
}

考虑一下是不是由于字符编码不对造成的

binary类型数据存的是16进制数据,需要hex(字段名)转换下

https://github.com/pingcap/tiflow/blob/68dc49cba0bfa7b30ca4fdd43f5fc50f9d094914/pkg/sink/codec/canal/canal_json_message.go#L255C26-L255C26

从代码里面看,如果字段类型是BinaryMySQLType,将使用ISO8859_1编码成字符串。

在上面 case 中 col9 使用 ISO_8859_1 解码后的数据为 \uFEFFabcd ,多了一个零宽不换行空格(Zero Width Non-Breaking Space,ZWNBSP, Unicode 中编码为\uFEFF )。不知道这个 零宽不换行空格 是TiDb 处理的还是使用的 SQL 客户端添加的 :joy:

这就不好说了。要从源头查一查了。下游入hdfs前,把对应字段用 ISO_8859_1 解码输出以下,如果还能对上,那就是入hdfs的时候有了变化。

其实对应字段已经被编码成了 ISO_8859_1 string,我觉得你入hdfs的时候可以直接把这两列设置为varchar,然后表的字符集设置成ISO_8859_1。