MyBatis 中的缓存机制就像图书馆的"热门书架"一样,能大幅提升数据查询效率。让我用一个故事来解释:
📖 故事场景
小明在电商网站工作,每次用户查询商品信息时,系统都要执行这样的 SQL:
SELECT * FROM products WHERE id = 1001
当 1000 个用户同时查询同一个商品时:
- 无缓存情况:数据库要执行 1000 次相同查询 😫
- 有缓存情况:只有第一次真正查数据库,后面 999 次直接从内存读取结果 ⚡
MyBatis 两级缓存详解
1️⃣ 一级缓存(本地缓存)
graph LR
A[SqlSession] --> B[执行查询]
B --> C{缓存是否存在?}
C -->|是| D[返回缓存结果]
C -->|否| E[查询数据库]
E --> F[存入缓存]
- 范围:同一个 SqlSession 内(相当于一次数据库会话)
- 特点:
- 默认开启,无需配置
- 执行
INSERT/UPDATE/DELETE
或调用clearCache()
时自动清空 - 类似浏览器缓存:刷新页面(新SqlSession)就失效
💡 例子:用户浏览商品详情页时,反复点击"刷新"按钮不会真正访问数据库
2️⃣ 二级缓存(全局缓存)
- 范围:Mapper 级别(所有 SqlSession 共享)
- 开启方式:
<!-- mapper.xml 中开启 --> <cache eviction="LRU" flushInterval="60000"/>
- 特点:
- 需要实体类实现
Serializable
接口 - 跨会话共享数据
- 可配置淘汰策略(LRU/FIFO)
- 事务提交后才存入缓存
- 需要实体类实现
💡 例子:用户A查询商品后,用户B在不同设备查询同一商品可直接获取缓存
🚀 缓存的核心价值
优势 | 说明 |
---|---|
性能提升 | 减少 90%+ 的数据库查询 |
降低负载 | 保护数据库不被高频查询压垮 |
加速响应 | 内存读取比磁盘快 100 倍 |
节省资源 | 减少网络传输和 SQL 解析开销 |
⚠️ 使用注意事项
- 数据一致性:更新操作需清空相关缓存
- 内存管理:缓存大对象可能引发 OOM
- 场景选择:
- 适合:读多写少的数据(商品信息/配置数据)
- 避免:实时性要求高的数据(库存/订单状态)