mybatis-plus实现乐观锁和悲观锁

目录

定义

场景

乐观锁与悲观锁

模拟修改冲突数据库中增加商品表

乐观锁实现

 悲观锁


定义

1)乐观锁

首先来看乐观锁,顾名思义,乐观锁就是持比较乐观态度的锁。就是在操作数据时非常乐观,认为别的线程不会同时修改数据,所以不会上锁,但是在更新的时候会判断在此期间别的线程有没有更新过这个数据。

2)悲观锁

反之,悲观锁就是持悲观态度的锁。就在操作数据时比较悲观,每次去拿数据的时候认为别的线程也会同时修改数据,所以每次在拿数据的时候都会上锁,这样别的线程想拿到这个数据就会阻塞直到它拿到锁。

场景


一件二手苹果手机,成本价是800元,售价是1000元。老板先是通知小李,说你去把商品价格增加500元。小李正在玩游戏,耽搁了一个小时。正好一个小时后,老板觉得商品价格增加到1500元,价格太高,可能会影响销量。又通知小王,你把商品价格降低300元。
此时,小李和小王同时操作商品后台系统。小李操作的时候,系统先取出商品价格1000元;小王也在操作,取出的商品价格也是1000元。小李将价格加了500元,并将1000+500=1500元存入了数据库;小王将商品减了300元,并将1000-300=700元存入了数据库。是的,如果没有锁,小李的操作就完全被小王的覆盖了。
现在商品价格是700元,比成本价低100元。几分钟后,这个商品很快出售了1千多件商品,老板亏10万多。

乐观锁与悲观锁


上面的故事,如果是乐观锁,小王保存价格前,会检查下价格是否被人修改过了。如果被修改过了,则重新取出的被修改后的价格,1500元,这样他会将1200元存入数据库。
如果是悲观锁,小李取出数据后,小王只能等小李操作完之后,才能对价格进行操作,也会保证最终的价格是1200元。


模拟修改冲突数据库中增加商品表

准备一张商品表

存入苹果手机

 

这里以第二条数据作为例子举例

后台java模拟二人同时拿到数据并进行修改

运行测试:

 

 可以看到最后测试结果是老板拿到的结果是700,比成本价还低了100,这样的场景肯定是不符合实际的业务需求的

乐观锁实现

数据库中添加version字段

取出记录时 获取当前信息的version

select id,商品名,商品价格,version from 商品表 where id =2

更新数据时 version+1 如果where语句中的version版本号不对 则更新失败

update 商品 set 价格 = 新的价格,`version`=`version`+1 where id = 2 and `version` = 1

 

 mybaits-plus相关调整

后台中表相对的实例对象添加对应version字段 并添加@Verison注解

 添加mybatis-plus插件

@Configuration
public class MybatisPlusConfig {

    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor(){
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        //添加乐观锁插件
        interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
        return interceptor;
    }
}

注意把刚才的价格重新改回1000再重新测试:

注意看此时的更新sql, 小李的更新sql+500成功了,小王的-300失败了,所以此时老板查到的结果应该是1500

 此时可以看到,两者的修改并没有发生冲突,但是也出现了新的问题,就是小李的修改成功了,但是小王的却修改失败了,遇到这种情况的话小王可能要面临卷铺盖的风险啊,为了不让小王卷铺盖,我们这里可以为小王添加一个修改重试的功能

 

 再次测试下,注意要把价格重新改回1000哦:

此时结果显示老板查询到的就已经是他想要的结果1200了

 悲观锁

悲观锁解决方案非常简单 直接在操作sql中添加 for update语句即可

select id,商品名,商品价格,version from 商品表 where id =2 for update

使用 for update操作 可以认为是给每次操作都加上表级别的悲观锁 在事务没结束前 其他事务必须等待加锁的事务提交后才可以

 注意:并发环境下都不建议使用悲观锁,因为悲观锁容易锁表,导致事务等待,性能低下。 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值