在高并发场景下,数据库的并发控制是确保数据一致性的关键。乐观锁和悲观锁是两种常见的并发控制机制,它们分别适用于不同的场景。MyBatis-Plus 提供了对乐观锁的支持,使得开发者可以轻松实现并发控制。本文将详细介绍乐观锁与悲观锁的概念、MyBatis-Plus 如何实现乐观锁、实现乐观锁的场景,以及如何使用 @Version
注解进行版本控制。
1. 乐观锁与悲观锁的概念
1.1 乐观锁(Optimistic Lock)
- 核心思想:假设并发冲突的概率较低,允许多个事务同时读取数据,但在提交时检查数据是否被修改。
- 实现方式:通过版本号(Version)或时间戳(Timestamp)实现。
- 适用场景:读多写少、并发冲突较少的场景。
1.2 悲观锁(Pessimistic Lock)
- 核心思想:假设并发冲突的概率较高,事务在读取数据时直接加锁,阻止其他事务修改数据。
- 实现方式:通过数据库的锁机制(如
SELECT ... FOR UPDATE
)实现。 - 适用场景:写多读少、并发冲突较多的场景。
2. MyBatis-Plus 如何实现乐观锁
MyBatis-Plus 提供了对乐观锁的支持,通过 @Version
注解实现版本控制。以下是实现乐观锁的步骤:
2.1 添加乐观锁字段
在实体类中添加一个版本号字段,并使用 @Version
注解标记:
@Data
public class User {
private Long id;
private String username;
private Integer age;
private String email;
@Version // 标记为乐观锁字段
private Integer version; // 版本号
}
2.2 配置乐观锁插件
在 MyBatis-Plus 的配置类中启用乐观锁插件:
@Configuration
public class MybatisPlusConfig {
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor()); // 添加乐观锁插件
return interceptor;
}
}
2.3 乐观锁的工作原理
- 初始读取:事务读取数据时,会获取当前的版本号。
- 更新数据:事务更新数据时,会检查版本号是否与读取时一致。
- 如果一致,则更新数据并递增版本号。
- 如果不一致,则抛出
OptimisticLockException
,表示数据已被其他事务修改。
2.4 乐观锁的通常处理
2.4.1 重试机制
通过循环或者递归实现重试逻辑。
@Service
public class UserService {
@Autowired
private UserMapper userMapper;
public static final int MAX_RETRIES = 3; //最大重试次数