MyBatis 一级缓存在分布式下的坑你知道吗?

前言:

最近生产环境的余额系统在扣减余额时经常出现余额够但是提示余额不足无法扣减的情况。查看代码逻辑,发现会先查询一次判断余额是否够,再实际扣减,之后查看日志发现并没有执行查询语句就返回错误了,推测可能是 MyBatis 一级缓存没有关闭引起的脏数据问题。关闭一级缓存后果然恢复正常了。

所以有了这篇文章,验证下 MyBatis 一级缓存的生效条件。

一级缓存

MyBatis 默认会开启一级缓存,在同一次会话中,如果执行多次查询条件相同的 SQL,会进行优化,优先命中一级缓存,避免多次查询数据库。

这样在单机环境下是没有问题的,可以减少于数据库的交互。但是生成环境一般都是多机部署,这样一级缓存开启的情况下就容易出现脏数据。

接下来做两个实验验证下。

测试 1

public void test1() {
   
    SqlSession sqlSession = sqlSessionFactory.openSession(true);
    UserWalletMapperExt mapper = sqlSession.getMapper(UserWalletMapperExt.class);

    System.out.println(mapper.queryUserBalance(10L, 1));
    System.out.println(mapper.queryUserBalance(10L, 1));
    System.out.println(mapper.queryUserBalance(10L, 1));
    mapper.addBalanceByType(10L, 1, 100L);
    System.out.println(mapper.queryUserBalance(10L, 1));
    System.out.println(mapper.queryUserBalance(10L, 1));
}
...queryUserBalance:debug:181 ==>  Preparing: select balance from user_wallet WHERE user_id = ? and type = ? 
...queryUserBalance:debug:181 ==> Parameters: 10(Long), 1(Integer)
...queryUserBalance:debug:181 <==      Total: 1
200
200
200
...addBalanceByType:debug:181 ==>  Preparing: update user_wallet set balance = balance + ? where user_id = ? and type = ? 
...addBalanceByType:debug:181 ==> Parameters: 100(Long), 10(Long), 1(Integer)
...addBalanceByType:debug:181 <==    Updates: 1
...queryUserBalance:debug:181 ==>  Preparing: select balance from user_wallet WHERE user_id = ? and type = ? 
  • 3
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值