【问题排查】记多线程事务提交问题排查
问题的现象是:一个定时任务主要是用来下载网银流水,有时任务执行时间非常短,有时执行时间较长,执行时间不一,查了下某几个流水数据,有时能下载成功,有时下载失败。
排查过程:
-
首先想到是多线程导致的问题,因为最近刚有同事将单线程下载流水改为多线程执行(将所有账户分成5批,用5个线程一起下载),仔细看了下代码发现下载流水的时候有个标志位,下载循环账户的时候每次都会去判断标志位,如果标志位已经被更新成成功,下载就终止。由此判断当一个线程下载成功后更新了下载成功标志位,导致其他线程下载终止。
-
改掉上述问题之后(如果是多线程执行不去判断该标志位),仍然时不时还会出现没有下载完全部账户的问题。于是又认真看了代码觉得没有什么问题。最后觉得可能是抛了异常,导致线程终止。又去看了下后台代码日志,发现在任务开始的时候去设置下载任务开始的标志位的时候,出现了事务执行失败,并回滚的异常日志。由此判断应该是多个线程同时去设置下载标志位,执行的过程是先删除后新增,多个线程同时执行新增操作,第一个线程执行成功了,其他线程再执行新增的时候,就会出现主键冲突。
总结:
- 多线程问题排查,问题不好重现,主要还是以看代码和日志为主,排查代码问题。
- 数据库事务虽然会保证事务执行的正确性,但是仍然会抛出异常,异常的处理也很重要。写多线程代码的时候要尽量避免数据的竞争。