由于Mybatis缓存导致问题的排查

130 阅读2分钟

问题说明:

维护一个历史的代码,在测试阶段发现一个问题.同一个数据库的同一个表相同查询条件两次查询返回值不同.

排查过程:

首先在第二次查询的地方打断点.查看数据库内数据是否有变化,发现数据库数据无变化.

怀疑是有事务导致数据还未写入数据库.

放开断点代码执行完成,查看数据库,数据依然和第一次查询相同.那么第二次查询的数据为什么不一样呢?

难道代码里面有多次更新再更新导致ABA变化?

修改日志级别改成debug.打印所有sql语句

同样在第二次查询地方打断点.查看日志updata关键字.没找到更新的sql.所以排除ABA修改原因

打开断点,执行第二次查询,发现没有打印查询的sql.基本可以确定是缓存导致.

为什么第二次查询的数据不同呢?

全局查询代码关键字set***.发现代码有多处修改查询字段的地方.所有修改的地方打断点.看看代码执行到了那个set.

再次执行代码果然有一个set修改了数据,之后再次查询发现数据发生变化.

问题可以定位就是缓存导致的查询数据不一致.

复现问题:

由于工程代码量较大,所以需要自己重建工程复现问题. 创建springboot,导入mybatis-plus包,具体如创建工程导入包版本就不说了.很简单

增加配置

mybatis-plus:
  configuration:
    cache-enabled: true

增加查询方法

@Transactional
public void testGetAndGet() {
    TestJson testJson = this.baseMapper.selectById(3);
    System.out.println("testJson is " + testJson.getName() + testJson.getId() + testJson.getUserDesc());
    testJson.setUserDesc("{"abc": "1234"}");
    TestJson testJson1 = this.baseMapper.selectById(3);
    System.out.println("testJson is " + testJson1.getName() + testJson1.getId() + testJson1.getUserDesc());

}

注意需要事务注解.因为默认的缓存方案是事务的.

执行上面的方法,会发现二次查询是修改之后的数据

好了,问题定位了.说起来挺简单.但是排查过程还是花了一天时间.定位到二次查询不同就花了很多时间.

解决:

知道问题原因解决就看业务需求了.

简单粗暴就是关闭缓存

再就是分析业务逻辑,修改实现方案