DML *** 作时,你乐观么?聊下MyBatis-Plus乐观锁

DML *** 作时,你乐观么?聊下MyBatis-Plus乐观锁,第1张

DML *** 作时,你乐观么?聊下MyBatis-Plus乐观锁 学习要求

良好的java基础, 熟悉SpringBoot框架,熟悉Mybatis框架

教学目标

了解并掌握MyBatis-Plus 乐观锁实现

视频教程

MyBatisPlus实战教程与开发建议

概念

多线程环境下如何保证数据库 *** 作安全呢?常用的一种解决方案就是对 *** 作数据表进行加锁处理。根据实现思路不同分:悲观锁与乐观锁2种。

悲观锁:悲观的认为多事务 *** 作同一数据是及其不安全的,所以A事务在 *** 作数据时,其他任何事务不允许对该数据进行修改,只能等待A事务 *** 作结束后才可以执行。

乐观锁:乐观的认为A事务在 *** 作数据时,期间不会有其他事务进行干扰,能顺利完成事务 *** 作。

实现

悲观锁

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

update 表  set  列=值 where 条件列=值   for update
select * from 表 where 条件列=值   for update

使用for update *** 作,可以认为是给每次 *** 作都加上表级别悲观锁,在事务没结束前,其他事务必须等待。

事务1

步骤1:启动事务

步骤2:使用悲观锁方式查询部门表(此时锁表)

步骤3:提交事务 

事务2

在事务执行到步骤2时,执行下面逻辑,发现事务停滞,等待事务1commit之后才继续往下执行。

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

乐观锁

乐观锁 *** 作跟悲观锁区别在于不对 *** 作的数据表进行加锁,而是使用version字段去规避。

以部门表为例子

步骤1:给部门表添加version列,默认值为0

步骤2:实现乐观锁 *** 作

需求: 修改id=1数据sn字段改为:kfb

1>先查询

select id, name, sn, version from department where id = 1;

得到该数据列version = 0

2>再修改, 注意version版本更新

update department set sn = "kfb", version = version + 1 where id = 1 and version = 0

这里有2个注意要点:

1:更新 sn字段的同时,version列数据也跟随变动

2:更新sql 除了基本的id=1条件外,多了version = 0 条件。

为什么要这么设计? 原因:乐观锁 *** 作没有加锁,任意事务都可以同步 *** 作,多事务同时 *** 作,总有一个先成功,一成功则修改了version字段值,其他事务version 条件自然就不上啦,update失败。

步骤3:判断更新是否成功

乐观锁判断是否更新成功,就看执行update语句之后,返回的影响数据行数,如果行数大于0表示修改成功,如果行数等于0表示修改失败,放弃这次修改,一切重来。直到修改成功为止。

MyBatis-Plus版乐观锁

MyBatis-Plus 使用@Version注解实现乐观锁

还是以部门表为例

步骤1:在部门表添加version字段

 步骤2:部门实体对象添加version字段

public class Department {
    //省略其他字段
    @Version
    private int version;
 
}

步骤3:配置类中配置支持拦截器乐观锁

@Bean
public MybatisPlusInterceptor optimisticLockerInterceptor() {
    MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
    interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
    return interceptor;
}

 步骤4:正常执行更新方法

@Test
public void testUpdate(){
    //先查询
    Department dept = departmentMapper.selectById(1L);
    //再替换
    dept.setId(1L);
    dept.setName("小卖部");
    dept.setSn("sell");
    //最后更新
    departmentMapper.updateById(dept);
}

 执行后SQL

UPDATE department SET name=?, sn=?, version=? WHERe id=? AND version=?

MyBatis-Plus会自动讲乐观锁逻辑加载到sql中

使用Mybatis-Plus注意:

乐观锁支持的数据类型只有:int,Integer,long,Long,Date,Timestamp,LocalDateTime 仅支持 updateById(id) 与 update(entity, wrapper) 方法 另外,每次 *** 作前都是先查询,替换,再更新,否则乐观锁无效

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zaji/5694786.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-12-17
下一篇 2022-12-17

发表评论

登录后才能评论

评论列表(0条)

保存