JPA 高并发下解决数据一致性
问题
小明跑到ATM机去取款,ATM实现逻辑读取卡上金额,输入取款金额,然后更新卡扣余额。一个人操作这张卡没有问题,如果是100个人使用这张卡就有问题,因为100个人同时获取卡内余额有可能都是同样的金额,更新金额的会导致金额不一致问题,这是程序处理就需要加上(乐观锁)或(悲观锁)了。
乐观锁
乐观锁其实在是在表中加上version字段,更新数据时将version字段+1,更新数据条件中version=当前version字段
update amount set money=money-100,version+1 where version=currentversion and id=?
乐观锁虽然能保证数据一致性,但是100同时执行,可能只有一部分数据更新成功,其他都会失败。
悲观锁
悲观锁是在读取数据时加锁,不允许其他线程操作。
select amount0_.id as id1_0_, amount0_.money as money2_0_, amount0_.username as username3_0_ from amount amount0_ where amount0_.id=? for update of amount0_
update amount set money=?, username=? where id=?
JPA说明
JPA中提供@Lock注解,解决数据一致性问题,防止出现脏数据。
使用方式
@Lock(value= LockModeType.PESSIMISTIC_WRITE)
@Query(value="from Amount o where o.id=?1")
Amount getByAmountId(long id);
LockModeType说明
LockModeType.PESSIMISTIC_WRITE 排他锁,有称为写锁,如果事务对数据加上排他锁,则其他事务不可并发读取数据,也不能加任何的锁。获取排他锁的事务既能读数据,又能修改数据。实现过程在原有sql加上for update语句,常用
LockModeType.PESSIMISTIC_READ 意向共享锁,有称为读锁,读取操作创建的锁。一旦上锁,任何事务无法对其修改,其他事务可以并发读取数据,也可在对此数据再加共享锁。实现过程在原sql加入 lock in share mode语句
LockModeType.NONE 不适用任何锁
LockModeType.OPTIMISTIC 乐观锁 需要version字段,常用
LockModeType.OPTIMISTIC_FORCE_INCREMENT 如果你希望用另一个实体来锁住对当前实体的引用,就需要使用它。 需要version字段,不常用
LockModeType.PESSIMISTIC_FORCE_INCREMENT 需要version字段,不常用
LockModeType.READ 需要version字段 ,不常用
LockModeType.WRITE 需要version字段,不常用
网友评论