MySQL乐观锁

前言

乐观锁是一种并发控制机制,它假设在大多数情况下不会发生冲突,因此在事务执行过程中不加锁。只有在提交时才会检查数据是否被其他事务修改过。如果数据在此期间被修改了,则当前事务会被回滚或者需要重新执行。乐观锁的主要用途和优势包括:

  1. 提高读取性能:由于乐观锁不会锁定资源,因此在读取数据时没有阻塞,可以极大地提高读取操作的性能,特别适合读多写少的应用场景。

  2. 减少死锁的可能性:因为乐观锁不使用实际的数据库锁,所以避免了传统悲观锁可能导致的死锁问题。

  3. 简化代码实现:乐观锁的实现通常比悲观锁简单,特别是在分布式系统中,因为它不需要复杂的锁管理逻辑。

  4. 支持高并发场景:在许多用户同时访问相同数据的情况下,乐观锁能够更好地处理并发请求,减少了等待时间,提高了系统的吞吐量。

  5. 用户体验改善:在Web应用等环境中,乐观锁可以减少用户界面的等待时间,提供更流畅的用户体验。

  6. 适用于长事务:对于那些涉及长时间运行的业务逻辑,采用乐观锁可以避免长时间持有锁导致的资源浪费。

  7. 支持离线或异步更新:乐观锁允许客户端在离线状态下进行数据修改,并在上线后合并这些更改,这在移动应用开发中尤其有用。

适用场景

  • 读多写少:当系统中读取操作远多于写入操作时。
  • 低冲突率:当数据项被多个事务同时修改的概率较低时。
  • 分布式系统:在分布式系统中,乐观锁可以简化跨节点的数据一致性问题。
  • 对最终一致性要求不高:如果应用程序可以接受短时间内的数据不一致,直到下一个成功的更新操作完成。

注意事项

  • 高冲突率下的效率降低:如果数据项频繁地被多个事务修改,乐观锁会导致大量重试,影响性能。
  • 版本号或时间戳的维护:需要正确设计和维护用于检测冲突的版本号或时间戳字段。
  • 业务逻辑复杂性增加:虽然乐观锁简化了某些方面,但处理冲突和重试逻辑可能会增加业务逻辑的复杂度。

1. 什么是乐观锁

乐观锁通常通过版本号(Version Number)时间戳(Timestamp)来实现。当一个记录被读取时,会同时获取它的版本号或时间戳。在更新这条记录之前,会再次检查这个版本号或时间戳,确保自上次读取以来没有被修改。如果有修改,那么更新操作将失败,应用程序可以根据具体需求选择重试或者其他处理方式。

1.1 使用版本号实现乐观锁

  1. 在表中添加一个版本字段,例如 version
  2. 读取记录时也读取版本信息。
  3. 更新记录时,根据版本号进行条件判断;
  4. 如果 UPDATE 语句影响的行数为0,说明在尝试更新的过程中,已经有其他事务修改了该记录,这时可以采取相应的措施,如提示用户数据已更改、重试等。

 比如这个SQL语句,更新会将版本号+1,同时只有版本号未有其他操作时才能执行成功。

UPDATE table_name
SET column1 = value1, column2 = value2, version = version + 1
WHERE id = some_id AND version = current_version;

 这种方式的优点是避免了锁定资源,提高了并发性能,但缺点是在高并发场景下可能会出现较多的重试情况。

1.2 使用时间戳实现乐观锁

第二种实现方式和第一种差不多,同样是在需要乐观锁控制的table中增加一个字段,名称无所谓,字段类型使用时间戳(timestamp),和上面的version类似,也是在更新提交的时候检查当前数据库中数据的时间戳和自己更新前取到的时间戳进行对比,如果一致则OK,否则就是版本冲突。

此方案有缺点,就是当并发事务时间间隔小于当前系统平台的最小时间单位时,会发生覆盖前一个事务结果的问题。

2. Mybatis实现乐观锁

通常的做法是通过版本号(version)字段来实现 

<insert id="isExistsUser" >select count(1) from t_users where userId = #{id}
</insert><select id="selectVersion" parameterType="user" resultType="long" >
select version from  t_users   where userName = #{userName} 
</select><update id="updateByVersion" parameterType="user">
update t_users set  version=version+1, password= #{password} where  userName = #{userName} and version=#{version}
</update><select id="selectUsers" resultType="int">select count(1)from t_userswhere id = #{id}
</select>

程序逻辑实现:

int userCount = UserMapper.selectUsers(id);
if (userCount==0) 
{Long version = UserMapper.selectVersion(user);int call = 0;user.setVersion(version);while (UserMapper.updateByVersion(user)==0) {if (call++==3) {break;}}
}

3. MyBatis-Plus实现乐观锁

以下时基于SpringBoot的实现,与非此方法大相径庭

3.1 添加依赖

首先确保你的项目中已经添加了 MyBatis-Plus 的依赖。如果你使用的是 Maven,可以在 pom.xml 文件中加入以下依赖:

<dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><version>版本号</version>
</dependency>

3.2. 配置乐观锁插件

在 Spring Boot 应用程序的配置类或主类中,你需要配置 MyBatis-Plus 的乐观锁插件。通常这一步是通过 MybatisPlusConfig 类来完成的。

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;@Configuration
public class MybatisPlusConfig {@Beanpublic MybatisPlusInterceptor mybatisPlusInterceptor() {MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();// 添加乐观锁插件interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());return interceptor;}
}

3.3. 实体类设置

在实体类中,需要添加一个字段来作为版本号。MyBatis-Plus 默认会识别名为 version 或带有 @Version 注解的字段作为乐观锁的版本号。

import com.baomidou.mybatisplus.annotation.Version;public class ExampleEntity {private Long id;private String data;@Versionprivate Integer version;// getters and setters
}

或者,如果你的版本字段名不是 version,你可以直接使用 @Version 注解指定它:

import com.baomidou.mybatisplus.annotation.Version;public class ExampleEntity {private Long id;private String data;@Versionprivate Integer optimisticLockVersion;  // 自定义名称// getters and setters
}

注意事项

  • 支持的数据类型包括:intIntegerlongLongDateTimestampLocalDateTime
  • 对于整数类型,newVersion 是 oldVersion + 1
  • newVersion 会自动回写到实体对象中。
  • 支持内置的 updateById(entity) 和 update(entity, wrapper)saveOrUpdate(entity)insertOrUpdate(entity) (version >=3.5.7) 方法。
  • 自定义方法更新时如果满足内置参数的参数条件方式也会执行乐观锁逻辑,例如自定义myUpate(entity) 这个和 updateById(entity) 是等价的,会提取参数进行乐观锁填充,但更新实现需要自行处理。
  • 在 update(entity, wrapper) 方法中,wrapper 不能复用。

3.4. 使用乐观锁

当你更新数据时,MyBatis-Plus 会自动处理乐观锁逻辑。例如:

@Service
public class ExampleService {@Autowiredprivate ExampleMapper exampleMapper;@Transactionalpublic void updateData(Long id, String newData) {ExampleEntity entity = exampleMapper.selectById(id);if (entity == null) {throw new RuntimeException("Entity not found");}entity.setData(newData);int result = exampleMapper.updateById(entity);if (result == 0) {throw new OptimisticLockingFailureException("失败了,请重试");}}
}

 这里,当调用 updateById 方法时,MyBatis-Plus 会自动检查并更新版本号。如果在尝试更新时发现版本号不匹配(即数据已被其他事务修改),则更新操作不会成功,返回值将是 0,这时可以抛出异常或进行重试。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/887745.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Springboot项目搭建(7)-Layout界面布局

1.概要 初步搭建了Layout界面的布局&#xff0c;其中包括左侧导航栏及其路由功能&#xff0c;和右侧头、体、脚部分的大致排版。最后在头部分中的昵称与头像替换成动态数据。 2.Layout主页布局 文件地址&#xff1a;src\views\Layout.vue 2.1 script行为模块 从elementUI中…

c语言的qsort函数理解与使用

介绍&#xff1a;qsort 函数是 C 标准库中用于排序的快速排序算法函数。它的用法非常灵活&#xff0c;可以对任意类型的元素进行排序&#xff0c;只要提供了比较函数即可。 qsort 函数原型及参数解释&#xff1a; void qsort ( void* base, //指向要排序的数组的首元素…

#渗透测试#红蓝攻防#HW#漏洞挖掘#漏洞复现01-笑脸漏洞(vsftpd)

免责声明 本教程仅为合法的教学目的而准备&#xff0c;严禁用于任何形式的违法犯罪活动及其他商业行为&#xff0c;在使用本教程前&#xff0c;您应确保该行为符合当地的法律法规&#xff0c;继续阅读即表示您需自行承担所有操作的后果&#xff0c;如有异议&#xff0c;请立即停…

(73)脉冲幅度调制PAM调制解调通信系统的MATLAB仿真

文章目录 前言一、PAM调制的基本原理二、PAM调制的步骤三、PAM调制示例四、PAM调制的应用五、MATLAB仿真1. 仿真代码2. 仿真结果 总结 前言 PAM&#xff08;Pulse Amplitude Modulation&#xff0c;脉冲振幅调制&#xff09;是一种模拟信号到数字信号的转换方式&#xff0c;它…

算法的NPU终端移植:深入探讨与实践指南

目录 ​编辑 引言 算法选择 模型压缩 权重剪枝 量化 知识蒸馏 硬件适配 指令集适配 内存管理 并行计算 性能测试 速度测试 精度测试 功耗测试 案例分析 图像识别算法的NPU移植案例 结论 引言 在人工智能技术的浪潮中&#xff0c;神经网络处理器&#xff08;…

汽车免拆诊断案例 | 2017款捷豹F-PACE车发动机偶尔怠速不稳

故障现象  一辆2017款捷豹F-PACE车&#xff0c;搭载2.0 L GTDi发动机&#xff0c;累计行驶里程约为16万km。车主反映&#xff0c;车辆组合仪表上发动机故障灯点亮&#xff08;图1&#xff09;&#xff0c;且发动机偶尔怠速不稳。 图1 发动机故障灯点亮 故障诊断 接车后试车…

不建模,无代码,如何快速搭建VR虚拟展厅?

不建模、无代码搭建虚拟展厅&#xff0c;可以借助一些专业的虚拟展厅搭建平台或工具来实现。以下是一些具体的步骤和建议&#xff1a; 一、选择平台或工具 首先&#xff0c;需要选择一个适合的平台或工具来搭建虚拟展厅。这些平台通常提供预设的展厅模板、拖拽式编辑工具和丰富…

数星星 (C++ 树状数组)

1265. 数星星 - AcWing题库 分析&#xff1a; 星星是按纵坐标递增给我们的&#xff0c;如果纵坐标相同&#xff0c;就按横坐标来给 所以星星是从低到高&#xff0c;一行一行来给的 题目要求我们去求每个等级的星星各有多少个 星星的等级由它左下角&#xff08;包括左边和下…

AIGC培训讲师人工智能培训讲师叶梓Python深度学习与AIGC培训提纲

【课程时长】 8天&#xff08;6小时/天&#xff09; 【课程简介】 随着AIGC&#xff08;基于AI的内容生成&#xff09;技术的崛起&#xff0c;以ChatGPT为代表的人工智能技术正引领全球科技潮流。为了帮助学员更好地理解和应用这一技术&#xff0c;特推出了本课程。 本课程…

GB28181系列三:SIP消息格式

我的音视频/流媒体开源项目(github) GB28181系列目录 目录 一、SIP消息Header字段 二、SIP URI(URL) 三、SIP路由机制 1、路由机制介绍 2、严格路由&#xff08;Strict Routing&#xff09;与松散路由&#xff08;Louse Routing&#xff09; 3、总结 四、SIP消…

STM32-C语言基础知识

C语言基础知识 stdint.h简介 给寄存器某个位赋值 给位6赋值为1流程&#xff1a;先清0&#xff0c;再赋值 带参数的宏定义 建议使用do {…}while(0)来构造宏定义 条件编译 条件编译后面必须跟宏语句&#xff0c;如#if _LED_H 指针使用常见的2大问题 1、未初始化 2、越界使…

计算机网络 实验八 应用层相关协议分析

一、实验目的 熟悉CMailServer邮件服务软件和Outlook Express客户端软件的基本配置与使用&#xff1b;分析SMTP及POP3协议报文格式和SMTP及POP3协议的工作过程。 二、实验原理 为了观察到邮件发送的全部过程&#xff0c;需要在本地计算机上配置邮件服务器和客户代理。在这里我…

若依解析(一)登录认证流程

JWTSpringSecurity 6.X 实现登录 JWT token只包含uuid ,token 解析uuid&#xff0c;然后某个常量加UUID 从Redis缓存查询用户信息 流程图如下 感谢若依&#xff0c;感谢开源&#xff0c;能有这么好系统供我学习。 设计数据库&#xff0c;部门表&#xff0c;用户表&#xff0c…

阿里巴巴即将超越OpenAI的o1?

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗&#xff1f;订阅我们的简报&#xff0c;深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同&#xff0c;从行业内部的深度分析和实用指南中受益。不要错过这个机会&#xff0c;成为AI领…

第29天 MCU入门

目录 MCU介绍 MCU的组成与作用 电子产品项目开发流程 硬件开发流程 常用元器件初步了解 硬件原理图与PCB板 常见电源符号和名称 电阻 电阻的分类 贴片电阻的封装说明&#xff1a; 色环电阻的计算 贴片电阻阻值计算 上拉电阻与下拉电阻 电容 电容的读数 二极管 LED 灯电路 钳位作…

Pump Science平台深度剖析:兴起、优势、影响与未来

在过去的几个月里&#xff0c;人们越来越关注去中心化科学&#xff08;DeSci&#xff09;。DeSci 是一种利用区块链技术进行科学研究的新方法。传统的科学研究经常面临所谓的“死亡之谷”&#xff0c;这指的是基础科学研究与成功开发和造福患者的实施之间的重要时期。DeSci 旨在…

Tülu 3:重新定义开源大模型的后训练范式

一、引言 在大型语言模型&#xff08;LLM&#xff09;的发展历程中&#xff0c;预训练阶段往往受到最多关注&#xff0c;动辄需要数百万美元算力投入和数万亿token的训练数据。然而&#xff0c;一个鲜为人知但同样关键的事实是&#xff1a;预训练完成的模型实际上并不能直接投…

Excel中根据某列内容拆分为工作簿

简介&#xff1a;根据A列的内容进行筛选&#xff0c;将筛选出来的数据生成一个新的工作簿(可以放到指定文件夹下)&#xff0c;且工作簿名为筛选内容。 举例&#xff1a; 将上面的内容使用VBA会在当前test1下生成5个工作簿&#xff0c;工作簿名分别为TEST1.xls TEST2.xls TEST3…

【电子通识】“标准的标准”:国家标准GB/T 1.1-2020 标准的分类

标准是可以分类的。比如根据层次、专业、对象、目的、功能等维度进行分类。 以层次进行分类&#xff1a; 可以分为国际标准、区域标准、国家标准、团体标准、企业标准、行业标准 以专业进行分类&#xff1a; 可以分为农业、医药、卫生、劳动保护、矿业、化工、机械等等。 以对象…

【网络安全设备系列】12、态势感知

0x00 定义&#xff1a; 态势感知&#xff08;Situation Awareness&#xff0c;SA&#xff09;能够检测出超过20大类的云上安全风险&#xff0c;包括DDoS攻击、暴力破解、Web攻击、后门木马、僵尸主机、异常行为、漏洞攻击、命令与控制等。利用大数据分析技术&#xff0c;态势感…