用户短时间内多次提交与保存带来的问题

Posted gulingjingguai

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了用户短时间内多次提交与保存带来的问题相关的知识,希望对你有一定的参考价值。

1.问题描述:

反馈,用户提交待办后,流程图中的状态没有改变

2.分析原因:

状态由数据库中待办的状态所决定,查明数据库,代办的状态为未提交,状态错误。

(此类问题由多线程访问冲突所致,无法进行问题重现。)

查日志:

查到的相关日志结果:

1.acviti报的Exception:can not find taskId

2.有一个请求(线程)成功执行了待办提交这个操作,

3.提示重复提交请求

4..update 。。。。set status = 0 。。。。。超时,

这条SQL语句更改的就是当前发生错误的待办,这条语句正是将待办状态改为未提交的罪魁祸首。

在查日志前,分析可能发生异常导致数据库回滚所致。但是当得知上面三条现象时,回滚就可以排除了。因为整个提交都是事务性的,但是,数据库并没有回滚的迹象,准确来说并不是所有的请求都回滚了。

 

此时开始关注线程竞争的情况(分析了用Redis实现锁的机制);

  刚开始关注多线程竞争情况的时候,只是关注提交待办这个接口的竞争,后来证明是不全面,理由有二,一是对代码不够熟悉,二是,先入为主的思想

按时间发生的顺序,体现到数据库的顺序,按线程确定每一个请求的状况:

当提交待办是,多次提交(网络有延迟),后面的等待锁,等到等获取到锁匙,activiti提交待办时,会找不到对应的taskId,因为此task已经被执行了,所以会发生can not find taskId异常。

根据日志提示分析保存待办的接口(此前一直认为这是service层的方法),它进行的操作就是保存待办参数,更新job一些参数,这里把status更新为0(这不是一个功能,只是默认值,为了重用提交待办的代码)。

这里的保存待办,发生了慢查询,等待锁20多s。

根据提交待办,保存待办,二者的顺序发生了逆转,提交待办后,保存待办又将状态改为了0,导致待办状态没有改变的假象。

 

线程运行模拟图:

技术分享图片

以上是关于用户短时间内多次提交与保存带来的问题的主要内容,如果未能解决你的问题,请参考以下文章

iOS解决按钮短时间内多次点击只触发一次事件方法

如何防止表单在 5 分钟内多次提交?

短时间内多次查询表格数据渲染问题

iOS解决按钮短时间内多次点击只触发一次事件方法

vue directive自定义指令防止按钮在短时间内多次点击

多次点击提交后如何只提交一次表单?