Mybatis 缓存学习


引用

缓存就是存贮数据(使用频繁的数据)的临时地方,由于取原始数据的代价太大了,因此我能够取得快一些。sql


一、一级缓存与二级缓存的差别

1)二级缓存默认关闭,一级缓存默认开启,二级缓存以Mapper的namespace为单位,可是一级缓存以sqlsession为单位,若是采用Spring管理对象,那么每次一个事务就会有一个sqlsession。数据库

2)二级缓存的读取都采用了锁控制并发,可是一级缓存并无,并且Mybatis强调了sqlsession不该该多线程共享,看到这里确实是有道理的,第一个是sqlsession关闭了在使用会报错,其二是读写缓存数据都没有加锁;然而,二级缓存虽然是创建在一级缓存之上,可是二级缓存采用了SynchronizedCache缓存,对数据的读写都进行了加锁,整个二级缓存就是一个责任链模式,从 SynchronizedCache(读写加锁)——>LoggingCache(命中率记录)——>SerializedCache(缓存值序列化、反序列化)——>LruCache(移除无用缓存)——>PerpetualCache(一级缓存,缓存数据的存储);缓存

3)二级缓存采用的Executor是BaseExecutor;二级缓存采用的Executor是CachingExecutor(内部委托BaseExecutor进行数据库操做);session


二、一级缓存代码

      
      if (cachedList != null) {
        list = cachedList;
      } else {
        
        try {
          list = doQuery(ms, parameter, rowBounds, resultHandler);
        } finally {
          localCache.removeObject(key);
        }
        localCache.putObject(key, list);
      }
    } finally {
      queryStack--;
    }
    if (queryStack == 0) {
      for (DeferredLoad deferredLoad : deferredLoads) {
        deferredLoad.load();
      }
    }
    return list;
  }


三、一级缓存的理解

所谓一级缓存,就是在一次会话当中,有可能重复执行彻底相同的查询语句,为了不数据库的压力,因此采用缓存的方式,第一次查询的数据放在缓存,第二次直接从缓存中获取数据,注意Java返回的是对象的引用,缓存的也是对象的引用,因此这个对象是可write的。PerpetualCache 就是一级缓存的实现。多线程

一级缓存是一个粗粒度的缓存,没有更新缓存和缓存过时的概念,对于一些隔离级别低的数据库,好比一个事务在查询数据时,另外一个事务还能够进行对数据库操做,那么致使前者读出的数据实际上是过期数据,那么这个时候的缓存就是有问题的,好比数据库隔离级别是 Read Committed , 那么两次读取的数据多是不一致的(不可重复读),但是因为缓存将会致使每次获得的数据都是一致的。并发


四、二级缓存代码

      if (cache != null) {
        flushCacheIfRequired(ms);
        
        try {
          if (ms.isUseCache()) {
            CacheKey key = createCacheKey(ms, parameterObject, rowBounds);
            final List cachedList = (List) cache.getObject(key);
            if (cachedList != null) {
              return cachedList;
            } else {
              List list = delegate.query(ms, parameterObject, rowBounds, resultHandler);
              tcm.putObject(cache, key, list);
              return list;
            }
          } else {
            return delegate.query(ms, parameterObject, rowBounds, resultHandler);
          }
        } finally {
          
        }
      }
    }
    return delegate.query(ms, parameterObject, rowBounds, resultHandler);
  }


五、二级缓存理解

CachingExecutor: 二级缓存执行器。灵活地使用 delegate机制。其委托执行的类是 BaseExcutor。 当没法从二级缓存获取数据时,一样须要从 DB 中进行查询,因而在这里能够直接委托给 BaseExcutor 进行查询。一级缓存就涉及到一个类PerpetualCache ,然而二级缓存则是一个责任链模式的结构,能够经过配置文件指定须要的缓存类app

六、二级缓存的设置

在Mapper文件中配置开启二级缓存ui

<cachespa

            eviction="FIFO"线程

            flushInterval="600000"  size="512"

            readOnly="true"

    />

相关文章
相关标签/搜索