当前位置:   article > 正文

mybatis-plus实现乐观锁_mybatis-plus 乐观锁

mybatis-plus 乐观锁

一、场景

业务并发现象带来的问题:秒杀   12306抢票,抢商品

1. 假如有100张票在出售,为了保证每张票只能被一个人购买,如何保证不会出现超买或者重复卖

2.对于这一类问题,其实有很多的解决方案可以使用

3. 第一个首先想到的是锁,锁在一台服务器中时可以解决的,但是如果在多台服务器下,锁就没有办法控制,比如12306有两台服务器在进行卖票,在两台服务器上都加锁的话,那也可能会导致在同一时刻有两个线程在进行卖票,还是会出现并发问题。

4. 接下来介绍的这种方式就是针对小型企业的解决方案,因为数据库本身的性能就是个瓶颈,如果对其并发量超过2000以上的就需要考虑其他的解决方案了。

二、乐观锁

在关系数据库管理系统中,乐观并发控制是一种并发控制的方法。它假设多用户并发的事务在处理时不会彼此互相影响,各事务能够在不产生锁的情况下处理各自影响的部分数据。在提交数据之前,每个事务会先检查在该事务读取数据后,有没有其他事务又修改了该数据。如果其他事务有更新的话,那么会放弃修改。

简单来说,乐观锁主要解决的问题是当要更新一条记录的时候,希望这条记录没有被别人更新,如果别人更新了那么我就不更新了。

三、乐观锁的实现方式

数据库表中添加version列,比如默认值给1
第一个线程要修改数据之前,取出记录时,获取当前数据库中的version=1
第二个线程要修改数据之前,取出记录时,获取当前数据库中的version=1
第一个线程执行更新时,set version = newVersion where version = oldVersion
newVersion = version+1 [2] (表示更新后的值)
oldVersion = version [1] (表示取出记录时的值)
第二个线程执行更新时,set version = newVersion where version = oldVersion
newVersion = version+1 [2]
oldVersion = version [1]
假如这两个线程都来更新数据,第一个和第二个线程都可能先执行
假如第一个线程先执行更新,会把version改为2,
第二个线程再更新的时候,set version = 2 where version = 1,此时数据库表的数据version已经为2,所以第二个线程会修改失败
反之同理
不管谁先执行都会确保只能有一个线程更新数据,这就是MP提供的乐观锁的实现原理分析。

四、mybatis-plus实现乐观锁的步骤

1. 在表中添加version字段作为版本号,int型

2. 在表对应的实体类的version属性上加版本号属性

  1. @Version
  2. private Integer version;

3. 配置乐观锁的拦截器,MybatisPlusInterceptor

  • 创建config包
  • 创建MpConfig的配置类,拦截器类型为MybatisPlusInterceptor
  1. @Configuration
  2. public class MpConfig {
  3. @Bean
  4. public MybatisPlusInterceptor mybatisPlusInterceptor(){
  5. MybatisPlusInterceptor mybatisPlusInterceptor = new MybatisPlusInterceptor();
  6. mybatisPlusInterceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
  7. return mybatisPlusInterceptor;
  8. }
  9. }

五、乐观锁的使用

想要实现乐观锁,首先就是要得到表中要查找的那条数据的version,然后拿version当条件,再将version加1更新回到数据库的表中。所以需要先对其进行查询。

  1. @Test
  2. void testLock(){
  3. //1.先通过要修改的数据Id,将当前数据查询出来
  4. //获得version字段值
  5. Employee emp1 = employeeMapper.selectById(1); //version=1
  6. Employee emp2 = employeeMapper.selectById(1); //version=1
  7. //2. 修改数据,假设emp2先修改完成,结果修改成功,version从1->2
  8. emp2.setEmail("zhangsan@qq.com");
  9. employeeMapper.updateById(emp2);
  10. //结果修改不成功
  11. emp1.setEmail("lisi@qq.com");
  12. employeeMapper.updateById(emp1);
  13. }

本文内容由网友自发贡献,转载请注明出处:https://www.wpsshop.cn/w/从前慢现在也慢/article/detail/435916
推荐阅读
相关标签
  

闽ICP备14008679号