JFinal中数据库使用乐观锁控制并发的问题!不可用model.update()

先贴上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,隔离级别为可重复读。

评论区

hb963724769

2019-05-30 13:57

表达能力有限,欢迎大家提问!

杜福忠

2019-05-30 14:57

我感觉 继承一下 MysqlDialect 再重写 forModelUpdate 后 super.forModelUpdate一下,再判断table对象里面有version字段没, 有的话再sql追加一个 and version 貌似就可以了 。forDbUpdate同样操作。还没试验,只是一个想法。

hb963724769

2019-05-30 15:21

@杜福忠 我来实验一波,加上and version = 传过来的version值,是我这么理解吧,但是这样是不是导致update的行数为0,之后return false;这个return fasle 代表的意思怎样区分是因为版本号错误引起的还是其他原因。

杜福忠

2019-05-30 15:59

@hb963724769 可能是我用的知识量少。 据我所知 其他错误 都是直接 抛的异常。 只有SQL正常执行,where不满足的时候才会 0 对于业务来说,感觉也没啥,都是“更新数据失败了,刷新一下试试”。。。

hb963724769

2019-05-30 17:45

@杜福忠 已测试,可行,贴上代码
if (modifyFlag.contains("updateCount") && null != attrs.get("updateCount")){
sql.append(" and ");
sql.append("`updateCount` = ").append(Integer.parseInt(String.valueOf(attrs.get("updateCount"))) - 1);
}

杜福忠

2019-05-30 18:10

@hb963724769 使用占位符 = ?,参数放data里

steven_lhcb_9527

2021-09-10 15:47

Innno读的时候默认不加锁,insert,update,delete默认加排他锁。

fmpoffice

2021-12-10 10:24

@hb963724769 楼主,请问是否只能这样写:Db.update("update `warehouse_stock` set money = (money - ?) where version = ? ...... verseion代表版本号。

hb963724769

2021-12-13 09:33

@fmpoffice 你后台开启事务,并且这个updateCount是页面传过来的话没问题

fmpoffice

2021-12-13 10:27

@hb963724769 恩恩,是的,开启了事务

热门分享

扫码入社