案情重演:
先从一张时序图开始
首先有两个系统A、B,他们之前用ActiveMQ作为交互。为了记录上面的执行情况,在数据库中有一个字段来标识执行到哪一步的状态,状态说明如下:
1: 插入数据库时的初始状态,即第1步完成后的状态
2: 推送ActiveMQ成功后的状态,也就是第2步完成后的状态
3: 处理结果成功的状态,也就是第6步完成后的状态【最终状态,下面会提到。】
正常来说从步骤1到步骤6都不会有任何问题,但并发量稍微大的时候,最终状态是2而不是3。
而日志打出来的结果已经更新成功,郁闷中,难道是数据库更新的问题?
后来在步骤6的更新数据库前,先查询该条记录判断状态是否为2。 然后下断点,调试,发现此时2的更新数据库操作未完成。
原因分析:
首先,推送MQ成功时并不代表已经处理完毕。
然后,当并发量达到一定程度时,MySQL需要处理大量的update操作,可能造成一定的延迟,
而且是多线程环境,步骤6由专门的线程来执行,跟步骤2实际上是并行的关系。
此时如果处理结果返回时,可能会在步骤2未能执行完毕的情况下执行步骤6成功,然后步骤2
的更新数据库操作会将本就是最终状态的记录变成步骤2完成的状态。
解决方案:
一、在第6步的更新数据库前先判断步骤2的数据库更新操作是否成功。
二、步骤1执行成功后直接推送MQ, 推送成功后不再update, 改为insert新记录到新表中, 查询的时候join一下新表即可。