为什么这道题总在面试里翻车
Mybatis 的一级缓存,很多初学者只觉得它是个“默认开启的 Map”,写个查询再查一次就能命中。但一旦深入源码,或者遇到分布式场景,问题就来了。你是否清楚:getMapper() 返回的对象和 selectOne() 的执行链路里,缓存到底绑定在哪个层级?SqlSession 关闭后缓存还在不在?更关键的是,当你的应用部署在多节点上,A 节点更新了数据并清除了本地缓存,B 节点为什么还能读到旧数据?这就是典型的“集群脏数据”问题。很多候选人能背出“一级缓存是 SqlSession 级别的”,却讲不清它底层依赖 Executor 的哪种实现,也说不明为什么二级缓存才勉强支持跨会话,而一级缓存天然不支持跨线程。这门课不教你怎么配 Mybatis,而是带你从源码出发,搞清楚缓存的生命周期、触发条件和失效边界,填补你“会用但不懂原理”的能力缺口。
先看哪几块,才能看懂后面的坑
建议学习顺序:先从 第 1 节 入手,理解getMapper() 与 selectOne() 的关系——这一步是后续所有分析的入口,不清楚代理对象如何创建,就看不懂缓存上下文怎么传递。接着看 第 2 节和第 4 节,前者用图示建立一级、二级缓存的整体框架认知,后者进入源码,追踪 CachingExecutor 和 BaseExecutor 中缓存的具体实现逻辑,重点盯住 PerpetualCache 的底层数据结构。然后必看 第 5 节,常用 Executor 类型(SimpleExecutor、ReuseExecutor、BatchExecutor)对缓存行为的影响截然不同,尤其是 CachingExecutor 作为装饰器如何包裹底层执行器,这是理解缓存是否生效的关键。最后看 第 3 节和第 6 节,第 3 节通过案例验证“更新语句为何会清除缓存”,涉及 flushCache 的配置陷阱;第 6 节直击痛点:集群环境下本地缓存导致的脏读问题,这是线上事故的常见根源。不要跳步,否则看到源码中的 clearLocalCache() 时你会一脸茫然。
学完你能独立回答什么、配合资料做什么
学完后,你应该能清晰解释:一级缓存的键是什么(SqlCommandKey)、为什么 update/delete/insert 默认会清空当前 SqlSession 的缓存、Executor 类型如何决定缓存行为、以及为什么生产环境不敢完全依赖一级缓存做数据一致性保障。配套练习建议:先手动画一遍 SqlSession → Executor → Cache 的调用链图,再用案例验证不同 flushCache 设置下的缓存命中情况,最后思考如何用 Redis 等外部缓存替代一级缓存来解决集群脏数据问题。不要只看不练,源码里的每个方法调用都可以对照实际执行过程去复盘。课程目录
1 01getMapper和selectone的关系 (07:40) 2 02mybatis源码分析一级二级缓存画图讲解 (07:06) 3 03mybatis的案例验证和更新清除缓存 (13:19) 4 04mybatis的一级缓存源码分析 (20:04) 5 05mybatis的常用Executor (06:59) 6 06mybatis的集群数据出现脏数据 (07:54)





