MyBatis多级缓存原理

蓝星 2020年03月31日 361次浏览

详见:https://tech.meituan.com/2018/01/19/mybatis-cache.html

一级缓存

一级缓存是基于SqlSession的,在一次会话中,如果连续两次执行的查询语句相同,那么第二次查询时不会真正去执行sql语句,而是返回第一次执行的缓存结果。 image.png

如图所示,在Executor执行sql查询语句时,会先判断执行的查询语句是否和上次查询语句相同,如果相同则直接从Local Cache中获取。

一级缓存配置

<setting name="localCacheScope" value="SESSION"/>

共有两个选项,SESSION或者STATEMENT,默认是SESSION级别,

  • SESSION:一个MyBatis会话中执行的所有语句,都会共享这一个缓存
  • STATEMENT:缓存只对当前执行的这一个Statement有效。

key组成

Statement Id + Offset + Limmit + Sql + Params 使用上述几个参数,合成CacheKey对象,并重写CacheKey的equal方法,保证两次sql查询语句时一样的。

失效时机

每次执行update时,会清除一级缓存 当配置成STATEMENT时会情况缓存

总结

  1. MyBatis一级缓存的生命周期和SqlSession一致。
  2. MyBatis一级缓存内部设计简单,只是一个没有容量限定的HashMap,在缓存的功能性上有所欠缺。
  3. MyBatis的一级缓存最大范围是SqlSession内部,有多个SqlSession或者分布式的环境下,数据库写操作会引起脏数据,建议设定缓存级别为Statement。

二级缓存

一级缓存生命周期仅限于SESSION级别,如果多个SESSION要共享缓存,则需要开启MyBatis的二级缓存。 二级缓存会使用CachingExecutor包装Executor,在执行sql语句时,会通过CachingExecutor执行二级缓存查询。 image.png

二级缓存开启后,同一个namespace下的所有操作语句,都影响着同一个Cache,即二级缓存被多个SqlSession共享,是一个全局的变量。

配置

开启二级缓存

<setting name="cacheEnabled" value="true"/>

因为同一个namespace下共享一个缓存,所以二级缓存不适用于多表联合查询,容易产生脏数据

对于分布式系统,我们可以实现Cache接口,使用Redis等缓存实现自己的缓存

失效时机

事务提交后,后续查询才能命中缓存 有session update数据后,缓存会失效

总结

MyBatis缓存命中过程 二级缓存>>一级缓存>>MySql 二级缓存实现了多个session之间共享缓存,但缓存都是基于本地的,想要改成分布式缓存困难比较大,所以一般应用中都会关闭缓存。