先贴上update方法中乐观锁的代码。
(versionModify && hasVersion){ Long versionDB = modelOld.getLong()Long versionForm = getLong()(!versionForm.equals(versionDB)){ RuntimeException()} Integer newVersion = getUpdateCount() + setUpdateCount(newVersion)} return super.update();
1、比如你的更新是,XXX.findbyId().setXXX.setUpdateCount(XX).update(),原意是想通过该写的方法去判断版本号,若不相等则抛出异常,
实际上,在非并发的情况的是没有任何问题的。
问题来了:当两个用户同时点击时候,A事务XXX.findbyId()这时候读出数据版本号为1,并通过XXX.findbyId().setXXX.setUpdateCount(XX).update();
在事务A未提交前,B也做了相同的事务,B事务通过XXX.findbyId()读取的版本号的值也是1,然后通过XXX.findbyId().setXXX.setUpdateCount(XX).update();这时候等待A事务执行完毕,B事务开始执行,因为这时候因为版本号的对比已经完成,所以B事务也成功提交了!导致A事务更新的值被B事务覆盖,甚至造成重复增加库存,或者重复扣减库存!
结论:通过model.update()更新数据,乐观锁将毫无意义。
解决方案:A:不通过model.update()方式更新数据,通过sql的update语句更新。
B:通过model.update()方式更新数据时,重写findById方法,在select * from a 结尾加上for update或者lock in sharemodel。
如果写的不对的地方,欢迎大家指正!数据库是mysql,隔离级别为可重复读。