1、概念一级缓存Local Cache一级缓存是默认开启的它是基于每个 SqlSession 的即在同一个 SqlSession 内查询的结果会被缓存在这个 SqlSession 中。当在同一个 SqlSession 中执行相同的查询语句时第一次查询会从数据库中获得结果并缓存后续相同的查询会直接从一级缓存中获取而不会再次访问数据库。一级缓存的生命周期与 SqlSession 相同。当 SqlSession 关闭或提交在执行 insert、update、delete 等修改操作后时一级缓存会被清空。二级缓存Global Cache二级缓存是跨 SqlSession 的并且需要手动开启。一旦开启它可以被多个 SqlSession 共享。当一个 SqlSession 执行查询操作而结果不存在于一级缓存时MyBatis 会查找二级缓存。如果二级缓存中也没有所需数据它才会执行数据库查询并将结果存放到一级缓存和二级缓存中。二级缓存的生命周期是跨 SqlSession 的其存活时间从 SqlSessionFactory 创建开始到 SqlSessionFactory 被关闭或应用停止时结束。执行查询操作的缓存查找顺序是这样的MyBatis 在当前 SqlSession 的一级缓存中查找是否有匹配的结果。如果一级缓存中没有找到MyBatis 会查找二级缓存中是否有匹配的结果如果二级缓存被开启并且适用于当前的查询。如果二级缓存中也没有MyBatis 才会执行数据库查询然后将查询结果放入一级缓存和二级缓存如果二级缓存已开启。在使用缓存时重要的是要注意数据一致性问题。一级缓存由于其生命周期较短绑定于 SqlSession通常不会引起严重的数据一致性问题。而二级缓存由于作用域更广不当的使用可能会导致数据不一致的情况因此在启用二级缓存时需要更加谨慎并考虑适当的缓存策略和失效机制。2、开启二级缓存有什么问题当针对同一个表的操作分布在不同的 Mapper XML 文件里并且启用了二级缓存的时候可能会出现数据一致性问题。这是因为 MyBatis 的二级缓存是基于 Mapper 的 namespace 来划分的每个 Mapper 的 namespace 都会有自己的缓存域。假设你有两个不同的 Mapper XML 文件分别是UserMapper.xml和AccountMapper.xml其中两者都对同一个用户表进行操作。如果两个 Mapper 都启用了二级缓存那么它们各自都会有一个独立的缓存区域。问题出现在当UserMapper中的一个操作导致用户表的数据发生变化后它只会清空UserMapper对应的二级缓存而不会影响AccountMapper的二级缓存。这意味着AccountMapper的二级缓存可能包含了陈旧的数据从而导致数据不一致。要解决这个问题你可以采取以下措施集中管理操作尽量将对同一个表的操作集中在同一个 Mapper 中这样同一个表的所有相关操作都会使用相同的缓存区域降低数据不一致的风险。禁用部分二级缓存如果确实需要分开管理不同的 Mapper你可以选择在操作频繁的 Mapper 中禁用二级缓存。自定义缓存失效策略可以通过自定义缓存的方式来实现跨 Mapper 的缓存失效策略。例如使用第三方缓存框架如 Ehcache、Redis时可以利用缓存框架的 API 来在一个 Mapper 更新数据后显式地清除其他 Mapper 的缓存。使用 MyBatis 的通知机制MyBatis 允许你配置缓存的清空策略例如可以在更新操作后使用flushCachetrue属性来指定清空缓存或者使用CacheNamespaceRef注解来引用同一个命名空间的缓存。谨慎使用二级缓存在涉及到数据一致性要求较高的业务场景中如果无法确保缓存的一致性最好是不要启用二级缓存或者将其应用于那些很少改变的数据。在设计缓存策略时重要的是要考虑到数据一致性、系统的复杂性以及缓存带来的性能提升做出适当的权衡。在 MyBatis 中启用二级缓存进行多表操作时可能会面对以下几个后果或问题尤其是当涉及到更新操作时数据一致性风险当对涉及多个表的数据进行更新操作时如果这些表都启用了二级缓存那么你需要确保在修改数据后及时更新或清空所有相关表的二级缓存。否则会存在数据不一致的风险因为其他用户可能会从缓存中读取到过时的数据。复杂的缓存管理多表操作通常意味着数据之间存在关联关系。在这种情况下缓存管理将变得更加复杂因为你可能需要实现更复杂的缓存失效策略以确保当一个表的数据发生变化时其他相关表的缓存也能相应地更新。难以追踪问题如果缓存配置不当或者使用不当可能会导致难以追踪的错误和问题比如脏读读取到未提交的数据和不一致的读取结果。性能问题虽然缓存的目的是为了提高性能但是不当的缓存使用特别是在多表操作中可能会导致性能问题。例如频繁清空缓存会降低缓存的效率而过多的缓存又可能消耗大量内存资源。事务管理挑战在启用了二级缓存的情况下处理跨多个表的事务操作会变得更加复杂。你需要确保缓存的一致性与数据库事务的一致性相匹配这可能会导致更加复杂的事务管理策略。为了避免这些后果你可以采取以下措施精心设计缓存策略只在查询频率高而更新频率低的表上启用二级缓存。使用更灵活、更强大的缓存框架例如 Redis、Ehcache它们提供了更加细粒度的缓存控制和失效策略。在进行数据修改操作时确保合理地清空或更新相关缓存。对于复杂的业务逻辑和数据关系权衡缓存带来的性能优势和可能的数据一致性风险有时关闭二级缓存可能是更好的选择。保证应用层的数据访问逻辑尽量简单明了避免引入过于复杂的缓存失效机制。总之开启 MyBatis 二级缓存时需要谨慎行事确保你完全理解其工作原理以及如何正确地管理缓存和数据一致性。在某些情况下特别是在数据一致性要求较高的场景可能需要禁用二级缓存或者选择其他缓存策略。