使用的是hibernate JPA, mysql 5.6
假设
线程T1读取钱包金额为100
同时
线程T2也读取钱包金额为100
T1 增加钱包金额10, 钱包金额=110;
T2 增加钱包金额5 , 钱包金额=105;
此时 T1 update 数据库记录为110;
T2随后 update 此时会将T1修改的数据给覆盖 为 105;
问题就出现了,后者更新覆盖了前者的更新,理论应该是 后者(T2) 增加5 ,应该在前者(T1) 更新数据之后的结果上增加
解决过程:
使用乐观锁:在钱包实体 增加
@Version
private int version;
字段 记录当前数据版本号,每次更新钱包时 同时自增当前version字段,后者更新时会比较当version版本是否一致,如果一致则更新成功,如果不一致将抛出异常 这时我们要手动捕获异常org.hibernate.StaleObjectStateException 再cath 里将需要处理的过程重新处理一遍即可解决。
附上别的解决方法:
对于对财务系统等对数据可靠性,正确性高的系统,可以使用 更新 金额钱 通过当前线程对 钱包表(或其它)
进行表锁:LOCK TABLES 表名 WRITE;
注意:此时当前锁住的表只有当前线程可以执行读取、更新,别的线程过来读取、更新 只能等待当前线程释放表锁,
此时就可以在当前线程内执行完成更新钱包记录然后释放锁
释放表锁:UNLOCK TABLES;
释放锁后等待线程就会执行。
因为是表锁,所以性能上肯定会有一定的影响,按需选择