• MybatisPlus 4 DML 编程控制 4.4 乐观锁


    CSDN话题挑战赛第2期
    参赛话题:Java技术分享

    MybatisPlus

    【黑马程序员2022新版SSM框架教程_Spring+SpringMVC+Maven高级+SpringBoot+MyBatisPlus企业实用开发技术】

    4 DML 编程控制

    4.4 乐观锁
    4.4.1 概念

    【一个问题】

    业务并发现象带来的问题: 秒杀

    • 假如有100个商品或者票在出售,为了能保证每个商品或者票只能被一个人购买,如何保证不会出现超买或者重复卖
    • 对于这一类问题,其实有很多的解决方案可以使用
    • 第一个最先想到的就是锁,锁在一台服务器中是可以解决的,但是如果在多台服务器下锁就没有办法控制,比如12306有两台服务器在进行卖票,在两台服务器上都添加锁的话,那也有可能会导致在同一时刻有两个线程在进行卖票,还是会出现并发问题
    • 接下来介绍的这种方式是针对于小型企业的解决方案,因为数据库本身的性能就是个瓶颈,如果对其并发量超过2000以上的就需要考虑其他的解决方案了。

    【简单来说,乐观锁主要解决的问题是当前用户要更新一条记录的时候,希望这条记录没有被别人更新。】

    4.4.2 实现思路

    乐观锁的实现方式

    • 数据库表中添加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,所以第二个线程会修改失败
      • 假如第二个线程先执行更新,会把version改为2
      • 第一个线程再更新的时候,set version = 2 where version = 1,此时数据库表的数据version已经为2,所以第一个线程会修改失败
      • 不管谁先执行都会确保只能有一个线程更新数据,这就是MP提供的乐观锁的实现原理分析。
    4.4.3 实现步骤

    ① 数据库表添加列

    列名可以任意,比如使用version ,给列设置默认值为1

    在这里插入图片描述

    在这里插入图片描述

    ② 在模型类中添加对应的属性

    根据添加的字段列名,在模型类中添加对应的属性值

    在这里插入图片描述

    ③ 添加乐观锁的拦截器

    package com.dingjiaxiong.config;
    
    import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
    import com.baomidou.mybatisplus.extension.plugins.inner.OptimisticLockerInnerInterceptor;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    
    /**
     * ClassName: MpConfig
     * date: 2022/9/24 15:21
     *
     * @author DingJiaxiong
     */
    
    @Configuration
    public class MpConfig {
    
        @Bean
        public MybatisPlusInterceptor mybatisPlusInterceptor(){
            //1 定义MP拦截器
            MybatisPlusInterceptor mybatisPlusInterceptor = new MybatisPlusInterceptor();
            //2 添加乐观锁拦截器
            mybatisPlusInterceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
            return mybatisPlusInterceptor;
        }
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27

    ④ 执行更新操作,观察拦截器是否生效

    @Test
    void testUpdate(){
        User user = new User();
        user.setId(3L);
        user.setName("Jock888");
        userDao.updateById(user);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    在这里插入图片描述

    看看数据库

    在这里插入图片描述

    可以看到这次修改并没有更新version字段,原因是没有携带version数据。

    “手动”添加version数据

    在这里插入图片描述

    发现传递的是1,MP会将1进行加1,然后,更新回到数据库表中。

    在这里插入图片描述

    所以要想实现乐观锁,首先第一步应该是拿到表中的version,然后拿version作为条件再将version加1更新回到数据库表中,所以在查询的时候,需要对其进行查询

    @Test
    void testUpdate(){
        //1. 先通过要修改的数据id 将当前数据查询出来
        User user = userDao.selectById(3L);  //这个数据是带有version的
        //2. 将要修改的属性逐一设置
        user.setName("Jock888"); //所以这个数据就是有version的
    
        userDao.updateById(user);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    运行测试

    在这里插入图片描述

    【上面是咱们用眼睛看出来的version值,这次是查出来的】

    查看数据库

    在这里插入图片描述

    原理就是这样。

    【加锁模拟】

    模拟A、B用户都来修改ID 为3 的这条数据。

    //模拟多人修改
    @Test
    void testUpdate(){
    
    
        //1. 先通过要修改的数据id 将当前数据查询出来
        User user = userDao.selectById(3L);  //  【A用户】 A 拿到的version = 3
    
        User user2 = userDao.selectById(3L);  // 【B用户】 B 拿到的version = 3
    
        //先让B用户把值改了
        user2.setName("Jock BBB用户改的"); //
        userDao.updateById(user2); // 【这是B用户干的】 B用户操作完后,version = 4
    
        //A 用户再改
        user.setName("Jock AAA用户改的");
        userDao.updateById(user);  // 等到A 用户再进行操作,version = 3 这个条件就不成立了
        
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    运行测试

    直接查看数据库

    在这里插入图片描述

    OK,这就很明显了,A 用户的修改操作并没有生效。

    查看日志

    在这里插入图片描述

    这就是乐观锁。

    MP 关于乐观锁的文档https://baomidou.com/pages/0d93c0/#optimisticlockerinnerinterceptor

    在这里插入图片描述

    【现在已经有插件 和 注解两种方式了】

  • 相关阅读:
    今年的数据安全风险点是什么?看数据
    【Linux】网络编程二:socket简介、字节序、socket地址及地址转换API
    【独立站运营】关于电子商务转化率,您还需要知道这些
    Python 人工智能 Machine Learning 机器学习基础知识点详细教程(更新中)
    宏与预处理
    Mac玩转Linux,如何在虚拟机安装操作系统centos,以及如何进行虚拟机快照、克隆连接,以及网络连接的三种方式,vi/vim编辑器使用
    前端工作总结295-uni-增加表单验证
    Ubuntu22.04.01Desktop桌面版 允许root用户远程登陆 笔记221110
    13 结构性模式-装饰器模式
    [EFI]ThinkPad-X13-Gen1-20T3电脑 Hackintosh 黑苹果efi引导文件
  • 原文地址:https://blog.csdn.net/weixin_44226181/article/details/127439133