数据库缓存问题

767 阅读3分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第14天,点击查看活动详情

Mybatis缓存

一级缓存

MyBatis的一级缓存是sqlSession级别的,即通过同一个sqLSession查询的数据会被缓存,再次使用同一个sqlsession查询同一条数据,会从缓存中获到

emp1、emp2是从同一个sqlSeeion获取的,因此在查询同一条语句时,查询语句只执行了一次,第二次则会从缓存中查找 image-20220910084759497.png

一级缓存失效情况

  • 不同的sqLsession对应不同的一级缓存
  • 同一个sqlsession但是查询条件不同
  • 同一个sqLsession两次查询期间执行了任何一次增删改操作
  • 同一个sqlsession两次查询期间手动清空了缓存

1、若在创建sqlSeesion2,区别于前一个sqlSession时,即使查询同一条语句 也会重新执行

image-20220910085041472.png 2、前边的查询的是id=1,若后边改成id=2,缓存就会失效

Emp emp1=mapper1.getEmpById(1);
System.out.println(emp1);
Emp emp2 = mapper1.getEmpById(2);
System.out.println(emp2);

3、当执行插入或删除语句后,会自动清理缓存

Emp emp1=mapper1.getEmpById(1);
System.out.println(emp1);
​
mapper1.insertEmp(new Emp(5,"aaa",20,"男"));
Emp emp2 = mapper1.getEmpById(1);
System.out.println(emp2);

4、手动清理缓存后也会重新执行

Emp emp1=mapper1.getEmpById(1);
System.out.println(emp1);
​
sqlSession1.clearCache();
//mapper1.insertEmp(new Emp(5,"aaa",20,"男"));
Emp emp2 = mapper1.getEmpById(1);
System.out.println(emp2);

二级缓存

MyBatis的二级缓存是sqLsessionFactory级别的,即通过同一个sqLsessionFactory所获取的sqLsession查询的数据会被缓存,在通过同一个sqLSessionFactory所获取的sqlSession查询相同的数据会从缓存中获取

MyBatis二级缓存开启的条件:

  • 在核心配置文件中,设置全局配置属性cacheEnabled="true",默认为true,不需要设置
  • 在映射文件中设置标签<cache/>
  • 二级缓存必须在sqlsession关闭或提交之后有效
  • 查询的数据所转换的实体类类型必须实现序列化的接口

二级缓存由于是sqlSessionFactory级别的,所以不再适用工具类,在满足上述条件后成功从缓存读取数据并且在二级缓存中会返回命中率等信息,但需要注意的是(存在增删改的操作时仍会清除缓存)

image-20220910092704631.png

二级缓存相关配置

在mapper配置文件中添加的cache标签可以设置一些属性:

  • eviction属性:缓存回收策略,默认的是 LRU。

    • LRU (Least Recently Used)-最近最少使用的:移除最长时间不被使用的对象。
    • FIFO (First in First out)-先进先出:按对象进入缓存的顺序来移除它们。
    • SOFT-软引用:移除基于垃圾回收器状态和软引用规则的对象。
    • WEAK-弱引用:更积极地移除基于垃圾收集器状态和弱引用规则的对象。
  • flushInterva属性:刷新间隔,单位毫秒

    • 默认情况是不设置,也就是没有刷新间隔,缓存仅仅调用语句时刷新
  • size属性:引用数目,正整数

    • 代表缓存最多可以存储多少个对象,太大容易导致内存溢出
  • readOnly属性:只读,true/false

    • true:只读缓存;会给所有调用者返回缓存对象的相同实例。因此这些对象不能被修改。这提供了很重要的性能优势。
    • false:读写缓存;会返回缓存对象的拷贝(通过序列化)。这会慢一些,但是安全,因此默认是false。

自定义缓存ehcache

依赖

<!-- ehcache -->
<dependency>
    <groupId>org.mybatis.caches</groupId>
    <artifactId>mybatis-ehcache</artifactId>
    <version>1.2.1</version>
</dependency><!-- slf4j日志门面的一个具体实现-->
<dependency>
    <groupId>ch.qos.logback</groupId>
    <artifactId>logback-classic</artifactId>
    <version>1.2.3</version>
</dependency>

ehcache.xml配置文件

<?xml version="1.0" encoding="UTF-8"?>
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:noNamespaceSchemaLocation="http://ehcache.org/ehcache.xsd" updateCheck="false">
​
    <diskStore path="D:/Java_Web/Mybatis_cache/cache"/>
​
    <defaultCache
            eternal="false"
            maxElementsInMemory="10000"
            overflowToDisk="false"
            diskPersistent="false"
            timeToIdleSeconds="1800"
            timeToLiveSeconds="259200"
            memoryStoreEvictionPolicy="LRU"/>
​
    <cache
            name="cloud_user"
            eternal="false"
            maxElementsInMemory="5000"
            overflowToDisk="false"
            diskPersistent="false"
            timeToIdleSeconds="1800"
            timeToLiveSeconds="1800"
            memoryStoreEvictionPolicy="LRU"/>
</ehcache>

二级缓存类型

<cache type="org.mybatis.caches.ehcache.EhcacheCache"/>

logback.xml

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <!--
    1、配置控制台的日志输入
    -->
    <!--    1.1、CONSOLE :表示当前的日志信息是可以输出到控制台的。-->
    <appender name="Console" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <pattern>[%level] %blue(%d{HH:mm:ss.SSS}) %cyan([%thread]) %boldGreen(%logger{15}) - %msg %n</pattern>
        </encoder>
    </appender>
​
​
    <!--
    2、配置日志输入的级别
        level(默认debug):用来设置打印级别,大小写无关:TRACE, DEBUG, INFO, WARN, ERROR, ALL 和 OFF
    -->
​
    <!--    2.1、设置某一个包或具体的某一个类的日志打印级别-->
    <!--    <logger name="com.lencamo" level="DEBUG" additivity="false">
            <appender-ref ref="Console"/>
        </logger>-->
​
    <!--   2.2、设置root下总的日志打印级别-->
    <root level="DEBUG">
        <appender-ref ref="STDOUT"/>
    </root>
​
    <logger name="com.sentiment.mapper" level="DEBUG"/>
</configuration>

此时执行,则会返回logback日志信息,并在指定目录生成缓存文件