MyBatis 缓存结构


0x00:什么是缓存

在网站的各种业务中,几乎离不开对数据库的增删改查操作,当一个功能点经常需要从数据库读取数据时,访问量大的网站,对数据库会造成很大的压力,这时候,为了缓解数据库的压力,提高运行速度,则缓存就是其中的一个解决办法。

缓存就是第一次用户发来的请求时,将请求的结果放到缓存中,之后其他用户发来同一个请求时,就会直接从缓存中读取第一次保存的数据,减小数据库压力的同时也提高了查询速度。

0x01:MyBatis 中的缓存

MyBatis 中的缓存有两种,一种是一级缓存,另外一种是二级缓存。

一级缓存其实就是 SqlSession 级别的缓存,在操作数据库的时候,每个 SqlSession 类的实例对象中都有一个数据结构 HashMap 可以用于存储缓存数据。不同的 SqlSession 类的实例对象缓存的数据区域 HashMap 是互不影响的。

二级缓存就是 Mapper 级别的缓存,多个 SqlSession 类的实例对象操作同一个 Mapper 配置文件中的 sql 句,多个 SqlSession 类的实例对象可以共用二级缓存,二级缓存是跨 SqlSession 的。

0x02:MyBatis 缓存模式

请输入图片描述

从以上图可以看出来,每个 SqlSession 类的实例对象自身有一个一级缓存,而查询同一个 Mapper 映射文件的 SqlSession 类的实例对象之间又共享同一个二级缓存。

0x03:MyBatis 一级缓存

一级缓存是存在于每一个 SqlSession 的实例对象中的,当我们第一次去查询某一个数据时,SqlSession 类的实例对象就会将这次查询到的数据放到一级缓存中,在没有对该数据进行增加或者修改或者删除时,以后的查询均会从缓存中读取,而不会在重新连接数据库做查询。其原理图如下:

请输入图片描述

上图画出了 MyBatis 一级缓存的原理,当第一查询 id 为 1 的用户时,因为缓存中没有相应的数据,所以回去数据库进行查询,然后将查询到的结果放到一级缓存中,随后查询时,均会到缓存中读取,而不会再去数据库中查询。

当有修改、添加、和删除的操作时,就会把缓存中的原有数据进行清空,目的是为了保持缓存中的数据是最新的,避免数据脏读。当进行过修改、添加或删除时,因为缓存数据已经被清空,所以下一次的操作会去数据库查询,然后再放到缓存中。

0x04:MyBatis 二级缓存

一级缓存是基于同一个 SqlSession 类的实例对象的,有时候查询操作的方法会封装到一个 service 方法中,当查询操作完毕后,service 方法就会结束,这时候 SqlSession 类的实例化对象就关闭了,也就意味着一级缓存会被清空(因为一级缓存是基于 SqlSession 类的实例对象的)。如果再次调用 service 去查询同一个信息时,就会重新打开一个 SqlSession 类的实例对象,由于一级缓存中这时候是空的,所以便无法再从缓存中获取相关信息。

这时候就可以使用二级缓存,二级缓存是基于 Mapper 的,当有多个 SqlSession 类的实例对象去加载同一个 Mapper 文件,并执行其中的 sql 配置时,他们便会去共同使用一个 Mapper 缓存。二级缓存原理同一级缓存类似,如下图:

请输入图片描述

二级缓存相对于一级缓存来说范围会更大,其多个 SqlSession 类的实例对象回去共享一个 Mapper。一个 Mapper 都有自己的一个二级缓存区域,其中是按照 namespace 来划分的,当两个或多个 Mapper 的 namespace 相同时,那么这些 Mapper 所执行的 sql 就会被缓存到同一个二级缓存中。

0x05:如何开启二级缓存

一级缓存是默认开启的,而二级缓存则需要手动开启,首先需要在 MyBatis 的全局配置文件 SqlMapConfig.xml 中配置 setting 属性,设置 cacheEnabled 为 true,代码如下:

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

因为二级缓存是基于 Mapper 文件的,所以第二步就需要在相应的 Mapper 文件中做配置,只需要添加一个 <cache/> 标签即可,代码如下:

<cache/>

0x06:总结

一级缓存是基于 SqlSession,二级缓存是基于 Mapper 的,在二级缓存中是以 namespace 为单位的,不同 namespace 下的操作互不干扰。使用二级缓存要注意的是,要保证该 Mapper 下的数据不会在其他的 Mapper 文件中有缓存,否则会得到不正确的结果,如果必须要使用,建议使用拦截器判断执行 sql 涉及到哪些表,然后把相关表的缓存清空。


更多关于代码审计、WEB渗透、网络安全的运维的知识,请关注微信公众号:发哥微课堂。



猜你喜欢

转载自blog.csdn.net/fageweiketang/article/details/80948439