1.伪代码及出问题原因
@Transactional(rollbackFor = Exception.class)
public void reward(){
//查询邀请人数
int total = invite.queryTotal(a);
//如果超出限制返回
if(total > 100){
return;
}
//绑定邀请关系
invite.insert(a,b);
//其他逻辑...
}
原因就是多个并发请求同时进逻辑后invite.queryTotal(a)查出来的都是小于100,此时没有锁住资源,造成了多个请求都走了后面的插入逻辑造成数据错误;
2.解决
(1)在invite.queryTotal(a)该代码sql中加入for update使用排它锁;则并发请求后,第一个请求查询到该处时,其他请求都要等待第一个请求事务提交后才能往下执行;
(2)此处能用共享锁LOCK IN SHARE MODE吗,答案是不可以; 以上代码,当并发请求后,第一个请求走查询后,其他请求不会等待第一个请求事务的结束,会依然查询成功后往下走;
那么应用场景可以在,如有一个接口需要走查询逻辑,另一个接口是更新逻辑;当同时查询某个共同值时,查询不会阻塞互相等待锁释放;但是当查询没结束事务另一个接口更新时,则阻塞;或一个请求更新没结束事务,其他查询阻塞等待更新成功;
本文由 GY 创作,采用 知识共享署名4.0 国际许可协议进行许可
本站文章除注明转载/出处外,均为本站原创或翻译,转载前请务必署名
最后编辑时间为:
2023/12/06 15:24