【问题处理】—— Mybatis缓存可改导致的异常

本文涉及的产品
日志服务 SLS,月写入数据量 50GB 1个月
简介: 【问题处理】—— Mybatis缓存可改导致的异常

现象:数组越界

        List<Integer> dateList = commonMapper.queryDateBefore(count);
        dateList.remove(0);
        return dateList.get(dateList.size() - 1);

报的是数组越界,错误下标是-1;然而我们从日志看commonMapper.queryDateBefore 返回的结果是8条;8条去掉1条,怎么会变成0了呢?


分析:缓存与返回同对象

一开始百思不得其解,翻遍日志,可以看到所有调用commonMapper.queryDateBefore的返回都是8条,而这里的List dateList是个局部变量,也不会有多线程来干扰


甚至看了remove()的源码,当然结果一无所获


直到后面打了断点,发现这个地方会执行多次,突然想到会不会是myBatis缓存问题,我们看到的日志是8没错,但是同一个线程多次执行此Sql,我印象中后续是会直接返回缓存,而不是再查数据库的,那myBatis自然不会再打印查询日志了,所以造成了所有查询的结果都是8条。


这其实有点让人意外,因为我一直认为myBatis的缓存是一种备份形式,没想到其缓存和返回值就是同一个对象,对查出来的数据进行修改后,再次查询其原值居然是错的


为了验证这种猜测,找到了缓存部分的源码:org.apache.ibatis.executor.BaseExecutor

48c8746c65954b8d902d20c1ba6ea4d9.png

果然,在查询list的时候,会把该list存储在缓存中再返回,如果我们对返回值进行操作,那实际也就是在操作缓存内容,导致本线程第二次查询时,得到错误的数据


结果:拷贝后修改

在查询出结果后,不直接对原list进行操作,而是对list采用一次部分深拷贝,然后再操作新集合

        List<Integer> dateList = commonMapper.queryDateBefore(count);
        ArrayList<Object> newDateList = new ArrayList<>(dateList);
        newDateList.remove(0);
        return newDateList.get(newDateList.size() - 1);
相关实践学习
日志服务之数据清洗与入湖
本教程介绍如何使用日志服务接入NGINX模拟数据,通过数据加工对数据进行清洗并归档至OSS中进行存储。
目录
相关文章
|
2月前
|
缓存 Java 数据库连接
Mybatis缓存相关面试题有多卷
使用 MyBatis 缓存机制需要注意以下几点: 对于频繁更新和变动的数据,不适合使用缓存。 对于数据的一致性要求比较高的场景,不适合使用缓存。 如果配置了二级缓存,需要确保缓存的数据不会影响到其他业务模块的数据。 在使用缓存时,需要注意缓存的命中率和缓存的过期策略,避免缓存过期导致查询性能下降。
58 0
|
1月前
|
SQL 缓存 Java
MYBATIS缓存
MYBATIS缓存
|
27天前
|
缓存 NoSQL Java
在 SSM 架构(Spring + SpringMVC + MyBatis)中,可以通过 Spring 的注解式缓存来实现 Redis 缓存功能
【6月更文挑战第18天】在SSM(Spring+SpringMVC+MyBatis)中集成Redis缓存,涉及以下步骤:添加Spring Boot的`spring-boot-starter-data-redis`依赖;配置Redis连接池(如JedisPoolConfig)和连接工厂;在Service层使用`@Cacheable`注解标记缓存方法,指定缓存名和键生成策略;最后,在主配置类启用缓存注解。通过这些步骤,可以利用Spring的注解实现Redis缓存。
51 2
|
17天前
|
SQL 缓存 Java
Java框架之MyBatis 07-动态SQL-缓存机制-逆向工程-分页插件
Java框架之MyBatis 07-动态SQL-缓存机制-逆向工程-分页插件
|
2月前
|
XML 缓存 Java
MyBatis二级缓存解密:深入探究缓存机制与应用场景
MyBatis二级缓存解密:深入探究缓存机制与应用场景
222 2
MyBatis二级缓存解密:深入探究缓存机制与应用场景
|
2月前
|
存储 缓存 Java
探秘MyBatis缓存原理:Cache接口与实现类源码分析
探秘MyBatis缓存原理:Cache接口与实现类源码分析
48 2
探秘MyBatis缓存原理:Cache接口与实现类源码分析
|
2月前
|
缓存 Java 数据库连接
MyBatis三级缓存实战:高级缓存策略的实现与应用
MyBatis三级缓存实战:高级缓存策略的实现与应用
57 0
MyBatis三级缓存实战:高级缓存策略的实现与应用
|
2月前
|
缓存 Java 数据库连接
【Mybatis】说一下 mybatis 的一级缓存和二级缓存
【Mybatis】说一下 mybatis 的一级缓存和二级缓存
|
2月前
|
Java 关系型数据库 MySQL
整合SpringBoot与MyBatis时报错时区异常
整合SpringBoot与MyBatis时报错时区异常
22 0
|
19天前
|
存储 缓存 NoSQL
redis缓存优化
采用获取一次缓存,如果为空的情况,获取分布式锁,让一个线程去重建缓存,另外的线程未获取到锁的情况,休眠短时间,然后再自旋获取缓存。
22 0