在这里插入图片描述

MyBatis 一级缓存与二级缓存的区别详解


🧠 一、缓存是什么?(类比故事)

想象你是个图书管理员(MyBatis),每次读者(应用程序)要借书(查询数据)时:

  • 无缓存:每次都跑去书库(数据库)找书,效率低。
  • 有缓存:把热门书放在前台小书架(缓存),下次直接取。

🔄 一级缓存(本地缓存)
  • 作用域SqlSession 级别(一次数据库会话)
  • 生命周期
    • SqlSession 创建而开启
    • SqlSession 关闭或清空操作(clearCache())而销毁
  • 默认开启:无需配置
  • 工作原理
    SqlSession session1 = sqlSessionFactory.openSession();
    User user1 = session1.selectOne("getUserById", 1); // 首次查数据库
    User user2 = session1.selectOne("getUserById", 1); // 直接从缓存取
    session1.close(); // 缓存销毁
    

📌 关键特点

  1. 同一个 SqlSession 内有效(比如同一个 HTTP 请求)
  2. 更新操作自动清空缓存(如执行 insert/update/delete
  3. 类似 “私人书架”,仅自己能用

🔄 二级缓存(全局缓存)
  • 作用域Mapper 级别(跨 SqlSession)
  • 生命周期
    • 随应用启动初始化
    • 随应用关闭或配置过期时间而失效
  • 需手动开启
``` - **工作原理**: ```java SqlSession session1 = sqlSessionFactory.openSession(); User user1 = session1.selectOne("getUserById", 1); // 查数据库,存入二级缓存

SqlSession session2 = sqlSessionFactory.openSession();
User user2 = session2.selectOne(“getUserById”, 1); // 直接从二级缓存取


📌 **关键特点**:
1. **跨会话共享**(多个用户/请求共享数据)
2. **需序列化实体类**(实现 `Serializable` 接口)
3. 类似 "公共图书馆",所有人可访问

---

####  ⚖️ 核心区别总结
| **特性**       | **一级缓存**                  | **二级缓存**                  |
|----------------|-------------------------------|-------------------------------|
| 作用域         | SqlSession 内部               | Mapper/Namespace 级别         |
| 生命周期       | 随 SqlSession 关闭而销毁      | 长期存在(直到配置过期)      |
| 是否默认开启   | 是                            | 需手动配置                    |
| 数据共享       | 仅当前会话可用                | 跨会话共享                    |
| 清空触发条件   | 执行 DML 操作或调用 clearCache() | 配置 flushInterval 或手动清除 |

---

####  🚨 缓存问题与注意事项
1. **脏读风险**:
 - 一级缓存:其他会话修改数据时,当前会话可能读到旧数据。
 - 二级缓存:多个应用共享缓存时可能不一致(需配合 Redis 等分布式缓存)。
2. **适用场景**:
 - 一级缓存:短时效、高频率查询(如用户权限校验)。
 - 二级缓存:读多写少、全局共享数据(如商品分类列表)。
3. **强制刷新**:
 ```xml
 <select ... flushCache="true"> <!-- 跳过缓存直接查库 -->

✅ 总结

一级缓存是 “会话级临时记忆”,二级缓存是 “应用级共享记忆”
前者轻量但隔离性强,后者高效但需谨慎管理一致性。
生产环境中,二级缓存通常结合 Redis 实现分布式扩展。

在这里插入图片描述

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐