MyBatis一级缓存默认开启且绑定单个SqlSession,失效属正常机制而非bug;需理解其触发点(如增删改、事务结束、clearCache等),避免跨会话误用,合理复用SqlSession,匹配业务节奏主动管理生命周期。

MyBatis 一级缓存默认开启,但它的“失效”往往不是 bug,而是机制使然。真正的问题在于开发者误以为它能跨会话、跨事务或长期保活。规避关键不在于阻止失效,而在于理解触发点、匹配业务节奏、主动管理生命周期。
同一查询在不同 SqlSession 中不命中缓存
一级缓存严格绑定单个 SqlSession,两个独立会话(哪怕查同一 ID)完全隔离,必然走库。
- 避免无意义地频繁创建新 SqlSession:例如在 Spring 环境中,用 @Transactional 控制事务边界,让 Mapper 方法复用同一个代理 SqlSession
- 非事务场景下,手动管理时尽量复用会话:比如批量查询前 openSession,查完统一 close,而非每查一次都 new 一个
- 若确实需要跨会话共享热点数据,不要依赖一级缓存——改用二级缓存或 Redis
执行增删改后后续查询不走缓存
这是强一致性设计:只要执行了 update/insert/delete,MyBatis 会立即清空当前 SqlSession 的全部一级缓存,防止读到脏数据。
- 无需规避该行为——它本就是正确逻辑。重点是别在同个会话里“先改后查还指望缓存”
- 若业务要求更新后立刻查最新值,直接查即可;若需多次读取更新结果,可在 update 后重新 select,此时会走数据库并重建缓存
- 避免在长生命周期 SqlSession 中混杂读写操作(如 Web 请求中持有一个 session 干所有事),易引发内存膨胀和预期外的缓存震荡
事务提交或回滚导致缓存清空
commit() 或 rollback() 调用时,MyBatis 主动清空缓存,确保事务结束后下一次查询看到的是持久化后的状态。
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
立即学习“Java免费学习笔记(深入)”;
- Spring 声明式事务下,方法结束即 commit,所以事务方法内第二次相同查询仍可命中缓存;但方法退出后缓存已不存在
- 如需事务后延续缓存效果,说明业务模型与一级缓存不匹配——考虑将读操作拆到只读事务或无事务上下文中
- 慎用 @Transactional(propagation = Propagation.REQUIRES_NEW),它会新建 SqlSession,旧缓存彻底不可见
手动调用 clearCache() 或配置 flushCache="true"
这两者都是显式清除信号,属于主动控制行为,不是意外失效。
- 检查 XML 映射文件中的 select 标签是否误加 flushCache="true",尤其在实时性要求高的查询中
- 避免在无关位置调用 sqlSession.clearCache();如确需刷新,建议只对特定 key 清理(一级缓存不支持局部清除,此时应换用二级缓存或自定义缓存方案)
- MyBatis-Plus 的某些 wrapper 查询默认 flushCache=true,使用时留意文档或源码行为
一级缓存不是万能加速器,它是轻量、短命、强一致的会话内优化手段。用得好,省 DB 压力;用得莽,反而增加排查成本。核心原则就一条:让它活在该活的范围内,别强求它做二级缓存或分布式缓存的事。

















