MyBtais的一级缓存和二级缓存原理、使用场景解析
✅ 一、一级缓存(Local Cache)—— 默认开启,SqlSession 级别
🔹 是什么?
- 作用域:同一个
SqlSession内 - 生命周期:从
openSession()到close()或commit()/rollback() - 默认开启,无需配置
🔹 工作原理
try (SqlSession session = sqlSessionFactory.openSession()) {
UserMapper mapper = session.getMapper(UserMapper.class);
User u1 = mapper.selectById(1); // 发起 SQL 查询
User u2 = mapper.selectById(1); // 不查数据库!直接返回缓存
System.out.println(u1 == u2); // true(同一个对象)
}✅ 第二次查询直接从 SqlSession 内部的 HashMap 中返回,不访问数据库。
🔹 什么时候失效?
- 执行了 INSERT / UPDATE / DELETE(任何写操作)
- 调用了
session.clearCache() session.commit()或session.close()
💡 注意:不同
SqlSession之间不共享一级缓存。
✅ 二、二级缓存(了解即可)(Second-Level Cache)—— Mapper 级别(跨 SqlSession)
🔹 是什么?
- 作用域:同一个 Mapper namespace 下的所有
SqlSession - 生命周期:应用级(只要不清理,一直存在)
- 默认关闭,需手动开启
🔹 如何开启?
步骤 1:在 MyBatis 主配置中启用(可选,默认已支持)
<settings> <setting name="cacheEnabled" value="true"/> <!-- 默认就是 true --> </settings>
步骤 2:在 Mapper XML 中声明使用缓存
<mapper namespace="com.example.UserMapper">
<cache /> <!-- 开启二级缓存 -->
<select id="selectById" resultType="User" useCache="true">
SELECT * FROM user WHERE id = #{id}
</select>
</mapper>步骤 3:实体类必须实现Serializable
public class User implements Serializable {
private static final long serialVersionUID = 1L;
// ...
}
🔹 工作流程
- 第一个
SqlSession查询selectById(1)→ 结果存入二级缓存 - 第二个
SqlSession查询selectById(1)→ 直接从二级缓存读取(不查 DB) - 如果执行了
updateUser()→ 整个 UserMapper 的二级缓存被清空
⚠️ 注意:只要 Mapper 中任意语句执行了写操作,整个 namespace 的缓存都会 flush!
⚠️ 三、大厂为什么不推荐用二级缓存?
虽然 MyBatis 提供了二级缓存,但在高并发、分布式系统中,它问题很多:
| 问题 | 说明 |
|---|---|
| 脏读风险 | 多节点部署时,A 节点更新数据,B 节点缓存未失效 → 返回旧数据 |
| 粒度太粗 | 按 Mapper 清缓存,无法精确到某条记录 |
| 序列化开销 | 对象要序列化/反序列化,影响性能 |
| 调试困难 | 缓存导致数据“看起来没更新”,排查成本高 |
✅ 大厂替代方案:
- 用 Redis / Caffeine 做应用级缓存(可控、分布式安全)
- 在 Service 层手动管理缓存逻辑(如 Spring Cache)
- 禁用 MyBatis 二级缓存(Spring Boot 默认也不开)
📌 真实情况:在阿里、字节等大厂项目中,从未见过生产环境开启 MyBatis 二级缓存。
✅ 四、一级 vs 二级缓存对比表
| 特性 | 一级缓存 | 二级缓存 |
|---|---|---|
| 作用域 | 单个 SqlSession | 同一个 Mapper(namespace) |
| 默认开启 | ✅ 是 | ❌ 否 |
| 跨 SqlSession | ❌ 否 | ✅ 是 |
| 跨 JVM | ❌ 否 | ❌ 否(仅单机有效) |
| 需要 Serializable | ❌ 否 | ✅ 是 |
| 大厂使用建议 | ✅ 安全可用 | ❌ 禁止使用 |
✅ 五、总结(背下来)
- 一级缓存:MyBatis 自带,安全、自动、无需管,但只在单次会话内有效。
- 二级缓存:不要用!用 Redis + 手动缓存控制才是正道。
- 缓存不是银弹:先优化 SQL 和索引,再考虑缓存。
如果你在面试中被问到二级缓存,一定要说:“了解原理,但生产环境我们用 Redis 替代,避免数据不一致问题。” —— 这才是大厂思维!
到此这篇关于MyBtais的一级缓存和二级缓存原理、使用场景解析的文章就介绍到这了,更多相关mybatis一级缓存和二级缓存内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!
相关文章
spring boot使用RabbitMQ实现topic 主题
本篇文章主要介绍了spring boot使用RabbitMQ实现topic 主题,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧2018-03-03


最新评论