緩存就是存貯數據(使用頻繁的數據)的臨時地方,由於取原始數據的代價太大了,因此我能夠取得快一些。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"
/>