Mybatis缓存的使用和注意事项

一级缓存:

mybatis默认开启一级sqlsession缓存,sqlsession指的是一次会话,就是通过数据库连接池获取连接,然后在不关闭本次连接的情况下进行增删改 称为一次会话。sqlsession内部由好几部分组成,比如Executor(好几种,cacheExecutor,selectExecutor,updateExcutro等等...)是用来执行增删改的,如果开启了1级缓存,他在连接数据库前会先执行本地缓存获取,每个sqlsession都有自己的缓存!

首先在本次会话中查询出的语句会被缓存到localCache里,这里我像理解IOC那样把他理解成一个容器,sqlsession通过 statementId 、 rowBounds 、传递给JDBC的SQL 和 rowBounds.limit (统称 select statment)等条件来计算出一个哈希值一样的结果,然后根据结果当做key去容器中判断是否有该缓存数据,有的话就直接从容器中拿省去了查询数据库的操作。

通过源码可以知道Executor内部确实有计算哈希值,存取缓存数据的代码,关于select的Executor会执行存取操作,所有增删改的操作又会清除本地缓存,会话关闭时也会清除本地缓存。

由此一级缓存问题也很明显,在一次sqlsession多次执行select的情况不多,所以出现读脏数据的情况也是很少......连接一中断又会清除本地缓存,个人感觉使用很鸡肋,没什么太大意义。

大佬的总结:

  1. Mybatis一级缓存的生命周期和SqlSession一致。
  2. Mybatis的缓存是一个粗粒度的缓存,没有更新缓存和缓存过期的概念,同时只是使用了默认的hashmap,也没有做容量上的限定。
  3. Mybatis的一级缓存最大范围是SqlSession内部,有多个SqlSession或者分布式的环境下,有操作数据库写的话,会引起脏数据,建议是把一级缓存的默认级别设定为Statement,即不使用一级缓存。

二级缓存:

二级取消了sqlsession独立的缓存,取代之的是根据namespace来创建的多个缓存容器,也就是说不管多少个sqlsession,只要执行mapper的namespace一样会使用同一个容器,默认不开启,需要在myabtis的配置处开启,并且在mapper里的xml文件里配置好缓存策略,由于二级缓存是每一个namespace一个容器,所以连表查询时无法使用,需要在mapper里通过Cache ref标签关联另外一个namespace,否则无法感应出其他表数据的变化导致读脏数据。

和一级缓存一样查询不会刷新缓存,增删改会刷新缓存数据。

个人感觉如果配置不当很容易发生脏数据读取,实际中多表联查较多的时候就会很容易少配置某个表导致出现脏数据,使用的好的话确实可以起到很好的本地缓存,但是相对于cachche比较麻烦容易出错,使用起来还是有些鸡肋,个人推荐使用cachche做本地缓存。

大佬的总结:

  1. Mybatis的二级缓存相对于一级缓存来说,实现了SqlSession之间缓存数据的共享,同时粒度更加的细,能够到Mapper级别,通过Cache接口实现类不同的组合,对Cache的可控性也更强。
  2. Mybatis在多表查询时,极大可能会出现脏数据,有设计上的缺陷,安全使用的条件比较苛刻。
  3. 在分布式环境下,由于默认的Mybatis Cache实现都是基于本地的,分布式环境下必然会出现读取到脏数据,需要使用集中式缓存将Mybatis的Cache接口实现,有一定的开发成本,不如直接用Redis,Memcache实现业务上的缓存就好了。

 

大佬的文章:https://www.jianshu.com/p/c553169c5921

发布了61 篇原创文章 · 获赞 54 · 访问量 6万+

猜你喜欢

转载自blog.csdn.net/bibiboyx/article/details/100982472