乐观锁
乐观锁认为并发冲突很少发生,不加锁,而是在更新时检查数据是否被其他事务修改过。
实现方式
版本号机制
-- 1. 查询数据(获取版本号)
SELECT id, count, version FROM stock WHERE id = 1;
-- 2. 更新数据(带上版本号条件)
UPDATE stock
SET count = count - 1, version = version + 1
WHERE id = 1 AND version = ?;
-- 3. 检查更新行数
-- 如果行数为0,说明版本号不对,需要重试或报错时间戳机制
类似版本号,使用时间戳代替版本号
SELECT id, count, update_time FROM stock WHERE id = 1;
UPDATE stock
SET count = count - 1, update_time = NOW()
WHERE id = 1 AND update_time = ?;CAS 机制(Compare And Swap)
CAS(Compare And Swap,比较并交换)是java进程中,乐观锁的一种实现方式,由CPU提供硬件级别的原子操作。
详细内容请阅读:CAS-Compare-And-Swap
Spring Data JPA 乐观锁示例
JPA(Java Persistence API) 是 Java EE 规范中定义的对象关系映射(ORM)标准接口,用于将 Java 对象持久化到关系型数据库中。
- 核心概念:
- 实体(Entity):使用
@Entity注解标记的 Java 类,映射到数据库表- 实体管理器(EntityManager):负责实体的增删改查操作
- JPQL(Java Persistence Query Language):面向对象的查询语言
- Spring Data JPA 是对 JPA 的进一步封装,提供了:
- 基于方法命名约定的自动查询生成
- 内置的 CRUD 操作支持
- 分页和排序功能
- 声明式事务管理
@Entity
public class Stock {
@Id
private Long id;
private int count;
@Version
private Long version;
// getters and setters
}
@Transactional
public boolean deductStockOptimistic(Long stockId, int quantity) {
Stock stock = stockRepository.findById(stockId).orElse(null);
if (stock == null || stock.getCount() < quantity) {
return false;
}
stock.setCount(stock.getCount() - quantity);
try {
stockRepository.save(stock);
return true;
} catch (OptimisticLockingFailureException e) {
// 版本冲突,需要重试或返回失败
return false;
}
}@Version 注解的自动机制
使用 @Version 注解后,JPA 会自动处理版本号的比较和更新,无需手动操作:
- 自动读取版本号:查询实体时,JPA 会自动加载
@Version标记的字段值 - 自动比较版本号:更新时,JPA 会自动生成带版本条件的 SQL:
UPDATE stock SET count = ?, version = version + 1 WHERE id = ? AND version = ? - 自动递增版本号:更新成功后,JPA 会自动将实体的版本号加 1
- 自动抛出异常:如果版本不匹配(更新行数为 0),JPA 会抛出
OptimisticLockingFailureException
不需要手动做的事情:
- 不需要手动传递 version 参数
- 不需要手动在 WHERE 条件中比较 version
- 不需要手动递增 version 值
需要注意的点:
@Version字段必须存在于实体类和对应的数据库表中- 支持的类型:
int,Integer,long,Long,short,Short,java.sql.Timestamp - 版本字段应使用
Long类型以避免溢出问题
乐观锁 vs 悲观锁
| 特性 | 乐观锁 | 悲观锁 |
|---|---|---|
| 并发性能 | 高 | 低 |
| 适用场景 | 读多写少 | 写多读少 |
| 实现方式 | 版本号/时间戳/CAS | select … for update |
| 冲突处理 | 重试/报错 | 阻塞等待 |
参考链接
- CAS-Compare-And-Swap - CAS机制详解(ABA问题与解决方案)
- 瑞幸后端-Q1-数据库事务传播行为和隔离级别