一、一级缓存(SqlSession 级缓存)
-
开启状态
- 默认自动开启,无需任何额外配置,也不能通过配置关闭,只能通过操作让其失效
-
作用域
- 作用域为
SqlSession级别 ,缓存数据仅在当前SqlSession内有效,不同SqlSession之间完全隔离
- 作用域为
-
核心特性
- 缓存命中条件 :同一
SqlSession内,执行SQL 语句 + 参数完全相同的查询,第二次及以后会直接读取缓存,不访问数据库 - 缓存自动清空场景 :执行
insert/update/delete写操作、SqlSession.commit()或SqlSession.rollback()时,一级缓存会被自动清空,保证缓存与数据库数据一致性 - 手动清空方式 :调用
SqlSession.clearCache()方法可手动清空当前SqlSession的一级缓存 - 序列化要求 :无,一级缓存存储在内存中,仅在
SqlSession生命周期内有效,无需实体类实现Serializable接口
- 缓存命中条件 :同一
二、二级缓存(Mapper 级缓存)
-
开启状态
-
默认关闭 ,需满足三个必要条件才能生效:
- 全局配置:
settings中cacheEnabled=true(默认值为true,若设为false会全局禁用二级缓存) - Mapper 配置:在对应
Mapper.xml中添加<cache/>标签(或使用注解@CacheNamespace) - 实体类要求:对应的实体类必须实现
Serializable接口,否则缓存数据无法序列化存储
- 全局配置:
-
-
作用域
- 作用域为
Mapper级别 ,按namespace隔离,不同namespace的 Mapper 缓存数据相互独立 - 同一
namespace的多个SqlSession可以共享二级缓存数据
- 作用域为
-
核心特性
- 数据写入时机 :二级缓存数据不会即时写入,需等
SqlSession关闭后,一级缓存中的数据才会同步到二级缓存 - 缓存清空规则 :执行
insert/update/delete写操作时,当前namespace的二级缓存会被自动清空 - 共享范围限制 :仅同一
namespace的SqlSession可共享,跨namespace无法共享
- 数据写入时机 :二级缓存数据不会即时写入,需等
三、 缓存读写流程
-
查询读取顺序(关键易错点)
- 优先级:二级缓存 → 一级缓存 → 数据库
- 流程:查询时先从当前
namespace的二级缓存获取;未命中则从当前SqlSession的一级缓存获取;仍未命中则查询数据库,查询结果会先写入一级缓存,SqlSession关闭后同步到二级缓存
-
数据写入顺序
- 数据库查询结果 → 一级缓存(即时写入) → 二级缓存(
SqlSession关闭后写入)
- 数据库查询结果 → 一级缓存(即时写入) → 二级缓存(
四、缓存配置
-
二级缓存全局配置
-
在 MyBatis 全局配置文件中,通过
settings标签配置cacheEnabled:<settings> <setting name="cacheEnabled" value="true"/> </settings> -
name属性值为cacheEnabled,value为true表示开启全局二级缓存支持(默认true)
-
-
二级缓存 Mapper 配置
- 在
Mapper.xml中添加<cache/>标签,可配置缓存淘汰策略(eviction)、刷新间隔(flushInterval)等属性
- 在
五、缓存设计原则与指标
-
缓存命中率
- 衡量缓存有效性的核心指标,命中率越高,说明更多请求从缓存获取数据,系统性能越好
-
缓存的优缺点
- 优点:降低数据库负载、提高系统响应速度、减少网络 IO 开销
- 缺点:增加数据一致性风险,需通过缓存清空、过期时间等策略保证缓存与数据库一致
-
数据一致性保障
- 写操作(
insert/update/delete)会触发对应缓存的清空,避免脏数据读取
- 写操作(
六、一级缓存 vs 二级缓存 核心对比表
| 对比维度 | 一级缓存 | 二级缓存 |
|---|---|---|
| 默认状态 | 自动开启 | 默认关闭 |
| 作用域 | SqlSession 级别 | Mapper (namespace) 级别 |
| 序列化要求 | 无 | 实体类需实现 Serializable |
| 共享范围 | 仅当前 SqlSession | 同一 namespace 的多 SqlSession |
| 写入时机 | 查询后即时写入 | SqlSession 关闭后写入 |
| 清空触发条件 | 写操作、commit/rollback | 写操作 |