Mysql和MyBatis的缓存机制
Mysql的查询缓存:
查询缓存是 MySQL 中一个曾经存在但已被弃用的功能。了解它对于理解 MySQL 的演进和为什么现在的优化方向不同很有帮助。
什么是查询缓存?
查询缓存将select语句的文本及其结果集以键值对的形式存储在内存中。当下一个完全相同的查询(字节对字节完全相同)到来时,MySQL 会直接返回缓存的结果,而无需再次解析、优化和执行查询。
缺点:
1.任何对底层表的修改(INSERT, UPDATE, DELETE, ALTER TABLE 等),都会导致所有引用该表的查询缓存全部失效。如果一个表更新频繁,那么针对这个表的查询缓存几乎无法有效利用。
2.查询必须完全相同(包括空格、大小写)。使用不同的数据库、不同的协议版本、不同的字符集,或者包含非确定性函数的查询都无法被缓存。
MyBatis的缓存机制:
一级缓存
一级缓存是 MyBatis 中最基本、默认开启的缓存。
一级缓存也叫本地缓存,它的作用域是一个SqlSession。在同一个SqlSession中执行相同的查询,MyBatis 会返回缓存的结果,而不会再次访问数据库。
一级缓存任何工作?
1.第一次执行select查询后,结果对象会被缓存到SqlSession内的一个 HashMap 中。
2.同一个SqlSession再次执行完全相同的 SQL 和参数时,会直接从缓存中取出对象返回。
3.如果中间发生了任何写操作(INSERT, UPDATE, DELETE)、执行了commit() 或rollback(),或者手动清空了缓存,该SqlSession的一级缓存就会被清空。
二级缓存
二级缓存的作用域更广,用于解决一级缓存无法跨SqlSession共享数据的问题。
什么是二级缓存?
二级缓存是Mapper级别的缓存,也叫做“全局缓存”。它的作用域是一个Mapper的 namespace(即同一个 Mapper 接口或 XML 文件)。多个SqlSession可以共享同一个二级缓存。
二级缓存是默认关闭的那么如何开启呢?
1.在 MyBatis 主配置文件中开启全局缓存支持。
<configuration><settings><!-- 显式地开启全局缓存 --><setting name="cacheEnabled" value="true"/></settings>
</configuration>
2.在具体的 Mapper XML 文件中配置<cache/>标签。
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.mapper.UserMapper"><!-- 启用本 Mapper 的二级缓存 --><cacheeviction="FIFO"flushInterval="60000"size="512"readOnly="true"/><!--SQL 定义--><select id="selectUserById" parameterType="long" resultType="User" useCache="true">SELECT * FROM user WHERE id = #{id}</select>
</mapper>
eviction:缓存回收策略。
LRU(最近最少使用,默认)
FIFO(先进先出)
SOFT(软引用)
WEAK(弱引用)
flushInterval:缓存刷新间隔(毫秒),不设置则无刷新。
size:最多可以缓存多少个对象引用。
readOnly:是否为只读。如果为 true,则返回相同的实例,性能好但不安全;如果为 false,则会返回序列化后的副本,安全但性能稍差。
工作机制
1.当一个SqlSession执行查询后,在关闭SqlSession时(或者执行commit()时),它才会将查询结果提交到二级缓存中。
2.另一个SqlSession执行相同的查询时,就可以从二级缓存中获取数据。
3.任何一个SqlSession执行了insert,update,delete操作并commit()后,会清空该Mapper namespace 下的整个二级缓存,以保证数据一致性。
缓存的查询顺序:
查询顺序
当开启二级缓存后,MyBatis 的查询顺序是:
二级缓存 -> 一级缓存 -> 数据库
1.先查找二级缓存。
2.如果二级缓存没有,再查找一级缓存。
3.如果一级缓存也没有,最后才去查询数据库。
4.查询到的数据会先存入一级缓存,在SqlSession关闭或提交时,再提交到二级缓存。
MyBatis缓存总结:
总结
一级缓存:默认开启,基于SqlSession,作用域小,生命周期短。主要用于解决一个会话内的重复查询。
二级缓存:需手动开启,基于Mapper,作用域大,生命周期长。用于解决跨会话的重复查询,但需要注意数据一致性问题