问题说明:
维护一个历史的代码,在测试阶段发现一个问题.同一个数据库的同一个表相同查询条件两次查询返回值不同.
排查过程:
首先在第二次查询的地方打断点.查看数据库内数据是否有变化,发现数据库数据无变化.
怀疑是有事务导致数据还未写入数据库.
放开断点代码执行完成,查看数据库,数据依然和第一次查询相同.那么第二次查询的数据为什么不一样呢?
难道代码里面有多次更新再更新导致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());
}
注意需要事务注解.因为默认的缓存方案是事务的.
执行上面的方法,会发现二次查询是修改之后的数据
好了,问题定位了.说起来挺简单.但是排查过程还是花了一天时间.定位到二次查询不同就花了很多时间.
解决:
知道问题原因解决就看业务需求了.
简单粗暴就是关闭缓存
再就是分析业务逻辑,修改实现方案