前言
- 在数据库当中有乐观锁和悲观锁,在我们更新数据的时候:
- 1.检索出更新数据,操作人员看;
- 2.操作人员修改数据;
- 3.保存更新数据
乐观锁:
- 认为一般不会冲突
- 1.数据提交时"是否有冲突检测"
- 2.没冲突提交,反正报错,并自定义处理
- mysql实现:
- 1.在表中加个version字段
- 2.取数据的时候连着version一起取出来
- 3.更新的时候,比对version是否一直,如果不一致表示失败
- 4.如果一致正常更新,version字段+1
- 程序实现:
- 1.在检索数据,将数据的版本号(version字段)检索出来;
- 2.在数据库执行update操作时,用检索出来的版本号与数据库中的记录做比较;
- 3.如果版本号一致就更新,反之就给出提示;
代码:
- 1.增加一个方法:getUserCoinForModel 注意:返回的是 整个Model
public UserCoinModel getUserCoinForModel(String userName){
QueryWrapper<UserCoinModel> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("username",userName);
return this.coinMapper.selectOne(queryWrapper);
}
public UserCoinModel getUserCoinForModel(String userName){
QueryWrapper<UserCoinModel> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("username",userName);
return this.coinMapper.selectOne(queryWrapper);
}
-
- 修改upgrade2方法 在第四部更新处检测是否有冲突,可以抛出异常不更新也可以更新一条默认数据。
@Transactional(rollbackFor = Exception.class)
public int upgrade2(String userName) throws Exception {
UserCoinModel userCoinModel = this.coinService.getUserCoinForModel(userName);
int getCoin=userCoinModel.getCoin();
int getVersion = userCoinModel.getVersion();
USER_LEVEL user_level = USER_LEVEL.BRONZE;
if(getCoin>=500 && getCoin<=1000){
user_level=USER_LEVEL.GOLD;
}else if(getCoin>1000){
user_level=USER_LEVEL.PLATINUM;
}
UserLevelModel userLevelModel = new UserLevelModel();
userLevelModel.setUserName(userName);
userLevelModel.setUserLevel(user_level.value());
if(this.coinService.updateVersion(userName,getVersion)!=1){
throw new Exception("升级失败");
}
return this.userLevelMapper.upgrade(userLevelModel);
}
悲观锁
- 总是最坏的情况:
- 1.每次拿数据都认为别人会修改数据,所以要加锁;
- 2.别人只能等待,直到释放锁才能拿到锁;
- 3.数据库的行锁、表锁都是这种方式;
- 4.悲观锁适用于读相对少,写相对多的操作;
- mysql实现
- 1.InnoDB默认是行级别的锁,当然必须命中索引或者主键(主键索引),是行级锁。否则是表级别。

- sql语句
select * from xxx where username for update
代码
public int getUserCoin(String userName){
QueryWrapper<UserCoinModel> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("username",userName);
queryWrapper.last("for update");
UserCoinModel userCoinModel = this.coinMapper.selectOne(queryWrapper);
if(userCoinModel==null){
return 0;
}else {
return userCoinModel.getCoin();
}
}