首页 > 其他分享 >乐观锁

乐观锁

时间:2025-01-02 19:41:43浏览次数:1  
标签:product 库存 版本号 更新 乐观 version

业务场景:商品库存更新

1. 数据库表设计

我们在商品表 Product 中添加一个 version 字段,用来实现乐观锁。每当库存更新时,都会检查并更新该字段的值。

sql CREATE TABLE product ( id BIGINT PRIMARY KEY, name VARCHAR(255), stock INT, version INT DEFAULT 1 -- 版本号字段,用来实现乐观锁 );

2. 实体类设计

在实体类中,通过 MyBatis-Plus 的 @Version 注解来标记 version 字段。

java import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableName; import com.baomidou.mybatisplus.annotation.Version; @TableName("product") public class Product { private Long id; private String name; private Integer stock; @Version // 使用 MyBatis-Plus 的乐观锁注解 @TableField("version") // 映射数据库中的 version 字段 private Integer version; // Getter 和 Setter }

3. 乐观锁更新库存操作

当用户进行购买时,我们首先查询商品库存,然后尝试更新库存。如果更新时发现版本号发生变化,说明该商品的库存已经被其他用户修改过,我们就会拒绝这次操作。

java public class ProductService { @Autowired private ProductMapper productMapper; public boolean purchase(Long productId, int quantity) { // 1. 查询商品信息 Product product = productMapper.selectById(productId); if (product == null || product.getStock() < quantity) { // 商品不存在或库存不足,购买失败 return false; } // 2. 扣减库存 product.setStock(product.getStock() - quantity); // 3. 使用乐观锁更新商品库存,version 字段自动处理 int updatedRows = productMapper.updateById(product); // 如果返回的更新行数为 0,说明版本号不一致,库存已经被其他用户修改 if (updatedRows == 0) { // 更新失败,可能因为并发冲突 return false; } return true; } }

4. 乐观锁执行过程

假设商品的 id = 1,初始库存为 10,版本号为 1。

  • 用户 A

    • 查询库存:库存为 10,版本号为 1。
    • 扣减库存:购买 5 个,库存剩余 5,版本号自增为 2。
    • 执行 updateById,更新成功,库存变为 5,版本号变为 2。
  • 用户 B

    • 查询库存:库存为 10,版本号为 1。
    • 扣减库存:购买 5 个,库存剩余 5,版本号自增为 2。
    • 执行 updateById但此时商品的版本号已经被用户 A 更新为 2
    • 用户 B 的更新操作失败,updateById 返回更新行数为 0,库存没有被更新。

5. SQL 生成过程

在执行 updateById 时,MyBatis-Plus 会自动生成类似如下的 SQL:

sql UPDATE product SET stock = stock - 5, version = version + 1 WHERE id = 1 AND version = 1;
  • 如果 version = 1,更新操作会成功,库存减少 5,version 增加到 2。
  • 如果 version 已经不是 1,说明其他用户已经更新了该记录,更新操作将失败,返回 0 行更新。

6. 乐观锁的优势:

  • 减少锁竞争:与悲观锁不同,乐观锁不需要在更新时对数据进行加锁,适用于读多写少的场景,能够提高系统的并发性能。
  • 避免死锁:乐观锁没有锁竞争,因此避免了死锁的发生。
  • 业务简洁:只需在实体类中标注 @Version,MyBatis-Plus 会自动处理版本号的增减。

7. 乐观锁的不足:

  • 冲突时可能会丢失更新:当多个用户几乎同时操作相同数据时,可能会因为版本号不一致导致更新失败,需要在业务逻辑中捕获异常并做重试或其他处理。
  • 适用场景有限:乐观锁适用于冲突概率低的场景,冲突频繁时,可能反而导致频繁的更新失败,效率低下。

标签:product,库存,版本号,更新,乐观,version
From: https://www.cnblogs.com/zyb-luckey/p/18648631

相关文章

  • MySQL中的锁类型,乐观锁和悲观锁是什么
    MySQL中的锁类型丰富多样,可以根据不同的分类标准来划分。以下是对MySQL中锁类型的详细归纳,以及对乐观锁和悲观锁的具体解释:一、MySQL中的锁类型1.按锁的粒度划分表锁:开销小,加锁快;锁定力度大,发生锁冲突的概率高,并发度最低;不会出现死锁。行锁:开销大,加锁慢;会出现死锁;锁定粒......
  • 乐观锁,悲观锁
    乐观锁和悲观锁是两种常见的并发控制机制,主要用于解决并发操作中的数据一致性问题。它们的应用场景和实现方式各有特点:1.乐观锁定义:乐观锁基于乐观的并发控制思想,假设事务间的冲突概率较低,因此不对资源加锁。在更新数据时,通过某种机制(如版本号或时间戳)来检测是否发生了冲突......
  • 乐观锁与悲观锁
    独占锁独占锁是一项悲观技术——它假设最坏的情况(如果你不锁门,那么捣蛋鬼就会闯入并搞得一团糟),并且只有在确保其他线程不会造成干扰(通过获取正确的锁)的情况下才能执行的下去。乐观锁对于细粒度的操作,还有另外一种更高效的方法,也是一种乐观的方法,通过这种方法可以在不发生干......
  • MySQL 的乐观锁和悲观锁是什么?
    MySQL的乐观锁和悲观锁是什么?在并发环境下,为了避免数据竞争和保证数据一致性,可以使用不同的锁策略。乐观锁和悲观锁是两种常见的并发控制机制,它们在锁定数据时的理念和实现方式上有显著区别。1.悲观锁(PessimisticLock)定义悲观锁是一种保守的并发控制策略,假设数据在被访问......
  • MySQL的各种锁(表锁,行锁,悲观锁,乐观锁,间隙锁,死锁)
    对于UPDATE、DELETE、INSERT语句,InnoDB会自动给涉及数据集加排他锁(X)。而MyISAM在执行查询语句SELECT前,会自动给涉及的所有表加读锁,在执行增、删、改操作前,会自动给涉及的表加写锁,这个过程并不需要我们去手动操作。那么在特定情况下,我们该如何去加锁呢?下面咱们来认真的......
  • MybatisPlus入门(十一)MybatisPlus-乐观锁
    一、乐观锁修改操作中的问题;乐观锁,琐是用来解决并发问题的。例如秒杀业务,上了100个秒杀单子,如果到了最后一个,8个人一起买,会出现问题,卖出第0号-1号-2号,小型并发解决方案:乐观锁。二、Mybatis-Plus乐观锁实现步骤Mybatis-Plus乐观锁实现步骤:步骤一......
  • 深入剖析 MyBatis-Plus:操作总结、对比与实践案例(CRUD 操作、分页、条件构造器、自动填
    MyBatis-Plus是MyBatis的增强工具,它极大简化了MyBatis的配置和操作,提高了开发效率。本文从基本操作到高阶用法,详细介绍了MyBatis-Plus的常见功能及与MyBatis的区别,并通过实际案例展示其强大的扩展能力。MyBatis-Plus基于MyBatis,但旨在减少开发者的代码量,增强可......
  • 【Java】并发编程的艺术:悲观锁、乐观锁与死锁管理
    目录一、乐观锁和悲观锁二、ReadWriteLock三、StampedLock四、Semaphore五、死锁的条件六、如何发现死锁七、如何避免死锁一、乐观锁和悲观锁        悲观锁(PessimisticLocking)具有强烈的独占和排他特性。它指的是对数据被外界修改持保守态度。因此,在整......
  • [官翻]mysqlbackup的乐观备份
    乐观备份可以用来提升备份和恢复体量比较大的数据库(只有少量的表经常变更)的性能。2)在大型数据库的热备份过程中(例如,以TB为单位),当备份进行时,可能会在服务器上生成巨大的重做日志文件。由于重做日志文件的增长速度快于mysqlbackup处理的速度,因此当mysqlbackup无法赶上重做日志周期,并......
  • [MySQL]实现乐观锁
    使用版本号在MySQL中,可以通过使用版本号(Version)来实现乐观锁。一种常见的实现方式是在表中增加一个版本号字段,每次更新数据时,都需要比对版本号。如果版本号一致,表示可以进行更新操作,否则表示其他事务已经修改了数据,需要进行相应的处理。下面是一个简单的示例,演示如何在MySQL......