使用jdbcTemplate.update(sql)进行insert batch操作,一个批量500条中会存在其中几条失败的场景

问题关闭,后续有了新的发现,可以确认与题目描述无关。

【 TiDB 使用环境】
操作系统:Centos7
集群:三台机器(pd,kv)
其他配置默认
image

【概述】 场景 + 问题概述
每天通过kafka进行约三千万数据批量逻辑消费,一批500;
最终会通过jdbcTemplate.update(sql)进行insert batch操作,每次执行时java服务无报错,tidb集群有WARN级别sql失败告警(但该警告与失败的sql无关),且update(sql)返回值为待插入数据大小。

发现过程为增加了日志与插入后马上查询对比的逻辑。

最终问题表现为数据丢失,但应用服务无告警。

【TiDB 版本】
4.0.12

【目的】
原子性,失败告警在应用程序有所反馈。


若提问为性能优化、故障排查类问题,请下载脚本运行。终端输出的打印结果,请务必全选并复制粘贴上传。

2赞

你发的这个问题,是想引用事务,体现一起失败,一起成功,还是什么?

建议你补充背景,配置信息,以及你的期望是什么

2赞

不好意思,编辑过程习惯性按了ctrl + enter,自动发布了。背景与配置信息、期望已补充。

2赞

是否开启了事务?

Session 引用的是 悲观事务,还是乐观事务? 事务处理失败,是否有后续的处理?或者记录?

2赞

我的认知来源是https://docs.pingcap.com/zh/tidb/v4.0/transaction-overview#tidb-%E4%BA%8B%E5%8A%A1%E6%A6%82%E8%A7%88
总结来说是,默认悲观事务,事务处理失败没有后续的处理,表盘没有对应的记录

2赞

举个例子
如果事务启用了,这一批数据就存在于一个事务内,那么执行结果: 要么全部成功,要么全部失败

如果没启用,则这一批数据,每执行一条就单独是一个事务,就是默认的事务模式

这么描述能理解么?

2赞

感谢,我大概理解您说的,但仍然有一些疑问。
第一个疑问是,批量的同一sql操作,会被拆分为不同的sql执行吗?doc对此似乎没有任何说明。
第二个疑问是,您说的”如果事务启用了“,是指什么参数的值指定呢?因为您最后说了”就是默认的事务模式“,如果没有开启事务,怎么会有事务模式呢?

2赞

我建议,你优先在 mysql Client 中来体验一下事务的操作

然后在考虑怎么从其他的服务来接入 mysql client,并启用事务

2赞

您这么说的话,就是需要显式使用BEGIN等来使用事务,这不太符合我的认知与文档描述。
理论上一条insert batch本身就是一个原子性的操作,就算没有事务也不应该部分成功。
其次是,启用事务并不是我的最终目的,我的最终目的是应用程序可以知道是否全部成功,如果有失败的,可以提示或者返回成功的数量,目前的情况是有丢失也不会有任何感知

2赞

了解下情况,update 的 sql 是那种一次 insert 多行的 SQL 然后写入的结果部分写入部分没有写入是吧

2赞

是的,请问您有什么好的建议或解决方案吗

2赞

我先说一下我的理解哈,怕理解错了,你的意思是:一个 insert values(),(),()… ,然后其中的几个 values 失败了,造成了数据不一致?

1赞

对的对的,就是这样的情形,请问有什么建议或者解决方案吗

1赞

我目前采用的比较紧急的方案是,每次插入后进行一次查询,发现其中缺漏的就再重试其中的该条数据

1赞

按道理是不会的,现在的信息都是现象,咱们有没有对应 失败时的 tidb- server的日志(现在的信息还是太少了)

2赞

另外,问一下,这个对比逻辑是怎么实现的,原理是啥能解释一下吗?没类似的案例,需要先把问题搞清楚

2赞

我们也没有找到tidb - server失败的日志,现在也比较怀疑查询对比的逻辑出现了不对劲的情况。对比的逻辑具体是:
1.拥有唯一约束 id + name + value
2.tk.mybatis search 查询 id_in and name_in,将唯一约束形成集合
3.将待插入的数据唯一约束判断是否存在

需要补充一个信息是,我们发现判断为不存在的信息,过后再次拨测接口时基本出现了重复,代码逻辑应该是没问题的,我们在看封装的tk之类的组件以及一些别的原因

好的,我这边的问题是,现在多数为现象,如果排查的话,希望咱们这边能尽量多提供一些信息,比如具体的一个 例子

1赞

主要是想确认下实际使用情况,明确多行的写入是否跨事务边界。现在这种情况的话,写入应该是在一个事务里。

1赞