ticdc 采集binlog到kafka,decimal精度丢失

【TiDB 使用环境】测试
【TiDB 版本】8.0.11-TiDB-v8.5.1
【操作系统】
【部署方式】云上部署(什么云)/机器部署(什么机器配置、什么硬盘)
【集群数据量】
【集群节点数】1
【问题复现路径】做过哪些操作出现的问题
【遇到的问题:问题现象及影响】
【资源配置】进入到 TiDB Dashboard -集群信息 (Cluster Info) -主机(Hosts) 截图此页面
【复制黏贴 ERROR 报错的日志】
【其他附件:截图/日志/监控】

ticdc 采集binlog到kafka,decimal精度丢失

采集文件,

CREATE TABLE universal_table (
id bigint unsigned NOT NULL AUTO_INCREMENT COMMENT ‘主键ID’,
uuid varchar(36) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT ‘UUID标识’,
name varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT ‘名称’,
short_name varchar(45) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT ‘短名称’,
code varchar(32) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT ‘代码’,
description text COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT ‘描述’,
short_code varchar(10) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT ‘短代码’,
medium_text mediumtext COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT ‘中等长度文本’,
long_text longtext COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT ‘长文本’,
count_int int DEFAULT NULL COMMENT ‘整型数量’,
count_bigint bigint DEFAULT NULL COMMENT ‘大整型数量’,
count_unsigned int unsigned DEFAULT NULL COMMENT ‘无符号整型’,
tiny_flag tinyint(1) DEFAULT NULL COMMENT ‘标志位(0/1)’,
tiny_unsigned tinyint unsigned DEFAULT NULL COMMENT ‘无符号小整型’,
small_value smallint DEFAULT NULL COMMENT ‘小整数值’,
price decimal(10,2) DEFAULT NULL COMMENT ‘价格’,
amount decimal(40,20) DEFAULT NULL COMMENT ‘金额(高精度)’,
rate decimal(8,4) DEFAULT NULL COMMENT ‘比率’,
precise_value decimal(64,20) DEFAULT NULL COMMENT ‘极高精度值’,
unsigned_decimal decimal(40,20) unsigned DEFAULT NULL COMMENT ‘无符号高精度值’,
zero_fill_decimal decimal(40,20) unsigned zerofill DEFAULT NULL COMMENT ‘zerofill高精度值’,
created_at timestamp DEFAULT CURRENT_TIMESTAMP COMMENT ‘创建时间’,
updated_at timestamp DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT ‘更新时间’,
event_date date DEFAULT NULL COMMENT ‘事件日期’,
event_time time DEFAULT NULL COMMENT ‘事件时间’,
event_datetime datetime DEFAULT NULL COMMENT ‘事件日期时间’,
precise_datetime datetime(6) DEFAULT NULL COMMENT ‘高精度日期时间(微秒)’,
json_data json DEFAULT NULL COMMENT ‘JSON数据’,
binary_data varbinary(64) DEFAULT NULL COMMENT ‘二进制数据’,
bit_flag bit(1) DEFAULT NULL COMMENT ‘位标志’,
fixed_char char(1) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT ‘固定长度字符’,
fixed_char_32 char(32) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT ‘32位固定长度字符’,
fixed_char_10 char(10) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT ‘10位固定长度字符’,
email varchar(320) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT ‘邮箱地址’,
phone varchar(20) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT ‘电话号码’,
address varchar(500) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT ‘地址’,
city varchar(100) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT ‘城市’,
country varchar(50) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT ‘国家’,
zip_code varchar(16) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT ‘邮政编码’,
url varchar(1024) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT ‘网址’,
image_url varchar(2048) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT ‘图片URL’,
long_url varchar(4096) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT ‘长URL’,
token varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT ‘令牌’,
hash_value varchar(128) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT ‘哈希值’,
color_code varchar(8) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT ‘颜色代码’,
status varchar(20) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT ‘状态’,
type varchar(32) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT ‘类型’,
category varchar(50) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT ‘分类’,
tag varchar(100) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT ‘标签’,
note varchar(500) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT ‘备注’,
title varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT ‘标题’,
subtitle varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT ‘副标题’,
first_name varchar(100) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT ‘名字’,
last_name varchar(100) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT ‘姓氏’,
full_name varchar(200) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT ‘全名’,
username varchar(50) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT ‘用户名’,
password_hash varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT ‘密码哈希’,
session_id varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT ‘会话ID’,
ip_address varchar(45) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT ‘IP地址’,
user_agent varchar(500) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT ‘用户代理’,
reference_id varchar(64) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT ‘参考ID’,
transaction_id varchar(128) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT ‘交易ID’,
order_number varchar(50) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT ‘订单号’,
product_sku varchar(100) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT ‘产品SKU’,
barcode varchar(128) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT ‘条形码’,
serial_number varchar(128) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT ‘序列号’,
version varchar(16) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT ‘版本号’,
locale varchar(10) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT ‘区域设置’,
currency varchar(5) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT ‘货币代码’,
language varchar(10) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT ‘语言代码’,
timezone varchar(50) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT ‘时区’,
xx_time12a datetime DEFAULT NULL,
xx_time12b datetime DEFAULT NULL,
xx_time12c datetime DEFAULT NULL,
xx_time12m datetime DEFAULT NULL,
PRIMARY KEY (id) /*T![clustered_index] CLUSTERED */
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci AUTO_INCREMENT=60006 COMMENT=‘通用表,包含多种字段类型’

INSERT INTO test3.universal_table
(id, uuid, name, short_name, code, description, short_code, medium_text, long_text, count_int, count_bigint, count_unsigned, tiny_flag, tiny_unsigned, small_value, price, amount, rate, precise_value, unsigned_decimal, zero_fill_decimal, created_at, updated_at, event_date, event_time, event_datetime, precise_datetime, json_data, binary_data, bit_flag, fixed_char, fixed_char_32, fixed_char_10, email, phone, address, city, country, zip_code, url, image_url, long_url, token, hash_value, color_code, status, type, category, tag, note, title, subtitle, first_name, last_name, full_name, username, password_hash, session_id, ip_address, user_agent, reference_id, transaction_id, order_number, product_sku, barcode, serial_number, version, locale, currency, language, timezone, xx_time12a, xx_time12b, xx_time12c, xx_time12m)
VALUES(6, ‘f618bee1-9206-11f0-be6e-0eedf5dac006’, ‘示例产品名称’, ‘示例2’, ‘PRD-001’, ‘这是一个示例产品的详细描述,用于演示INSERT语句的功能。’, ‘SC001’, ‘这是中等长度的文本内容,可以存储更多信息。’, ‘这是非常长的文本内容,可以存储大量信息,如文章内容、产品详情描述等。’, 100, 1000000000, 200, 1, 5, 500, 99.99, 123456789.12345678901234000000, 0.1250, 12345678901234567890.12345678901234567890, 123456789.12345678901234000000, 1.00000000000000000000, ‘2025-09-15 15:38:24’, ‘2025-12-04 07:04:43’, ‘2023-10-15’, ‘14:30:00’, ‘2023-10-15 14:30:00’, ‘2023-10-15 14:30:45.123456000’, ‘{“array”: [1, 2, 3], “key”: “value”, “nested”: {“field”: “data”}}’, NULL, 1, ‘Y’, ‘固定长度字符串32位测试数据’, ‘固定10位’, ‘example@email.com’, ‘+8613812345678’, ‘北京市朝阳区某某街道123号’, ‘北京市’, ‘中国’, ‘100000’, ‘https://www.example.com’, ‘https://www.example.com/images/sample.jpg’, ‘https://www.example.com/very/long/url/path/that/exceeds/normal/length/limits’, ‘eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9’, ‘5f4dcc3b5aa765d61d8327deb882cf99’, ‘#FF5733’, ‘active’, ‘product’, ‘electronics’, ‘new,popular’, ‘这是一个备注信息’, ‘示例产品标题’, ‘示例产品副标题’, ‘张’, ‘三’, ‘张三’, ‘zhangsan’, ‘$2y$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi’, ‘sess_abc123def456’, ‘192.168.1.100’, ‘Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36’, ‘REF-20231015-001’, ‘TXN-20231015-001’, ‘ORD-20231015-001’, ‘SKU-001’, ‘1234567890128’, ‘SN00123456789’, ‘1.0.0’, ‘zh_CN’, ‘CNY’, ‘zh’, ‘Asia/Shanghai’, NULL, NULL, NULL, ‘2025-09-22 19:21:51’);

image

较长的decimal都出现精度丢失

先看下写入tidb 的时候,精度是不是就丢了 博客 - 关于 decimal 精度问题 | TiDB 社区

1 个赞

@TiDBer_JRxiljos 是的,先确认一下 TiDB 精度是不是正常的

写入tidb是正常的 精度没有丢失
kafka的数据精度对不上了 这三个字段都会出现截断

无论是写入数据库就丢了,或者是cdc 的时候丢了,可以思考下能不做转化成str 再同步

1 个赞

kafka 消费的时候,如果有需要,
再转化成decimal 写入下游

decimal.handling.mode=string,这种是不丢失精度的

flink cdc mysql集成debezium可以通过debezium的这个参数来控制decimal类型的转换。

但是ticdc集成debezium没有看到这种类似的配置开放出来,控制debezium的行为。

上游是业务库,很多涉及金额的字段,也不能改业务库的金额为string类型

ticdc同步到kafka,精度已经丢失,下游无法恢复精度。虽然这种精度丢的很小。原则上影响不大

但是ticdc集成demezium的配置貌似是把decimal转为float来出来,对位数很长的数,会精度丢失,另外float可能精度不准,1变成0.99999999这种,影响业务和测试理解

期望是
1, 能不能通过调整flink cdc的源码来使用decimal.handling.mode=string逻辑来控制数据转换逻辑
2, 未来能否开放或封装debezium的原生配置作为ticdc的配置,从而用户可以更灵活的使用原生参数,控制写出数据的行为

说错了 能不能改ticdc的源码

这个不是社区能解决的问题了,需要去github 提issue,看有没有对应研发回你。你也可以看下是不是用的
最新版本的cdc 了

1 个赞

好的,我去试试看

参考这个图

https://docs.pingcap.com/zh/tidb/stable/dev-guide-sample-application-java-jdbc/#mysql-兼容性

可以考虑升级到 v8.5.4
另外,对ticdc 有依赖的,可以考虑使用 ticdc 新架构,你会有惊喜的
https://docs.pingcap.com/zh/tidb/stable/ticdc-architecture/

Debezium lost precision when data type is bigint or decimal · Issue #12064 · pingcap/tiflow · GitHub 是的,目前还不支持

蹲一个最优解

会不会是 数据类型映射不匹配导致的?

我以前从oracle导数据到tidb也出现过数据丢失, 不过是日期类型的

TiCDC 配置中开启了高精度 decimal 同步模式了吗?

尝试了canal-json,发现canal-json的decimal是不丢失精度的,4种事件类型的值,也符合期望

但是canal-json和debezium的数据结构不一样,flink层做结构适配,或者结构转换
携带的信息也各有优劣,但是核心信息都是有的。

目前计划采用canal-json格式,不使用debezium,打算基于一个flink程序,同时兼容两种数据格式的转换,由于历史很多程序都是基于debezium格式做的,因此在数据转换的源头程序flink种,尝试将canal-json的结构粗略转换为debezium的结构,降低下游程序的数据结构适配。

可以尝试使用字符串呀