Mybatis的一级、二级缓存?Mybatis的二级缓存什么时候会清理缓存中的数据?
MyBatis 一级缓存与二级缓存详解
MyBatis的一级缓存是基于PerpetualCache的HashMap本地缓存,作用域为Session,默认开启。二级缓存需要单独开启,作用域为Namespace或mapper,默认也是采用PerpetualCache,HashMap存储。
一、一级缓存(Local Cache)
- 作用范围:
SqlSession级别,默认开启。 - 生命周期:
- 缓存数据仅在当前
SqlSession有效。 SqlSession关闭或执行commit()、rollback()时,缓存清空。
- 缓存数据仅在当前
- 失效场景:
- 执行
INSERT/UPDATE/DELETE操作(无论是否提交)。 - 手动调用
sqlSession.clearCache()。
- 执行
- 特点:
- 减少同一会话内重复查询的数据库访问。
- 不支持跨会话共享,易受局部操作影响失效。
二、二级缓存(Global Cache)
- 作用范围:
Mapper级别(跨SqlSession),需显式开启。 - 配置方式:
在 Mapper XML 中添加<cache />标签,或通过@CacheNamespace注解启用。▼xml复制代码<!-- Mapper.xml 中启用二级缓存 --> <mapper namespace="com.example.UserMapper"> <cache eviction="LRU" flushInterval="60000" size="1024"/> </mapper> - 存储机制:
- 缓存数据序列化后存储(实体类需实现
Serializable接口)。 - 不同
Mapper的缓存相互隔离。
- 缓存数据序列化后存储(实体类需实现
三、二级缓存的清理时机
-
执行更新操作(INSERT/UPDATE/DELETE)
- 同一
Mapper的任意更新操作会触发二级缓存清空,确保数据一致性。 - 示例:
UserMapper.updateUser()执行后,UserMapper的二级缓存失效。
- 同一
-
手动调用清理方法
- 通过
SqlSession调用clearCache()仅清理一级缓存。 - 清理二级缓存:需获取
Cache对象并调用clear()。▼java复制代码sqlSession.getMapper(UserMapper.class); // 获取 Mapper Cache cache = sqlSession.getConfiguration().getCache("com.example.UserMapper"); cache.clear(); // 手动清理二级缓存
- 通过
-
达到刷新间隔(flushInterval)
- 若配置
flushInterval="60000",则每隔 60 秒自动清空缓存。 - 适用场景:对实时性要求不高的数据(如配置表),定期刷新缓存。
- 若配置
-
缓存淘汰策略触发
- 当缓存对象数量超过
size限制时,按策略(如LRU、FIFO)移除数据。 - 常见策略:
LRU(最近最少使用,默认)FIFO(先进先出)SOFT(软引用,依赖 GC)WEAK(弱引用,依赖 GC)
- 当缓存对象数量超过
-
事务提交(默认配置)
- 若未设置
flushCache="false",事务提交时自动清空关联Mapper的二级缓存。 - 注意:全局缓存可能导致跨会话数据不一致,需结合业务场景谨慎使用。
- 若未设置
四、二级缓存注意事项
-
数据一致性风险
- 多表关联查询时,若其他
Mapper更新数据,当前Mapper的缓存不会自动失效。 - 解决方案:通过
<cache-ref />关联其他Mapper的缓存,或手动清理。
- 多表关联查询时,若其他
-
序列化要求
- 缓存对象需实现
Serializable接口,否则可能抛出序列化异常。
- 缓存对象需实现
-
适用场景
- 读多写少的数据(如基础配置、历史记录)。
- 避免用于频繁更新的数据(如订单状态),防止缓存频繁失效。
五、缓存对比总结
| 特性 | 一级缓存 | 二级缓存 |
|---|---|---|
| 作用域 | SqlSession 内部 | Mapper 级别,跨 SqlSession |
| 存储位置 | 内存(未序列化) | 序列化后存储(可配置 Redis 等分布式缓存) |
| 默认状态 | 启用 | 需显式配置 |
| 清理触发 | DML 操作、会话关闭 | DML 操作、定时刷新、手动清理 |
| 性能影响 | 低开销,仅会话内复用 | 需序列化,跨会话共享,可能影响性能 |
六、配置优化建议
- 合理设置
flushInterval和size:根据数据更新频率和内存容量调整。 - 避免滥用二级缓存:优先通过业务层缓存(如 Redis)管理高频跨表数据。
- 监控缓存命中率:结合日志或监控工具分析缓存效果,及时调整策略。
理解 MyBatis 缓存机制及清理逻辑,有助于在高并发场景下平衡性能与数据一致性。
评论
问答助学
相关内容
0个评论
全部评论
点击登录,快来和大家讨论吧~
表情
图片
暂无评论
作者分享
使用spring boot 3.4.4 整合knife4j 4.4.0接口文档时,在访问接口文档时可能会出现错误java.lang.NoSuchMethodError:'void org.springframework.web.method.ControllerAdviceBean.<init>(java.lang.Object)',需在配置的全局异常类前添加@Hidden即可。详情见:https://springdoc.org/#Introduction
3
HashMap的put方法的具体流程?
2
路漫漫其修远兮......
1
ArrayList和LinkedList的区别是什么?
3
什么是服务雪崩,怎么解决这个问题?
3
