1. 程式人生 > >mybatis緩存的設計

mybatis緩存的設計

rim mysql 分享圖片 ted val exe transacti upd setting

繼續用提問的方式來看Mybatis的緩存設計。

1、Mybatis如何開啟緩存

Mybatis對查詢結果進行緩存,所以緩存的對象為具體的Statement

通過在Statement上是否使用緩存來啟用。

<select id="selectByPrimaryKey" parameterType="java.lang.Long" resultMap="BaseResultMap"  fetchSize="5" statementType="PREPARED" useCache="true" >
useCache默認值為true

2、誰持有緩存?

Mybatis中有兩個對象持有緩存。

CachingExecutor以及BaseExecutor

技術分享圖片 技術分享圖片

CachingExecutor和SimpleExecutor的關系是持有的關系
public class CachingExecutor implements Executor {

  private final Executor delegate;
  private final TransactionalCacheManager tcm = new TransactionalCacheManager();

技術分享圖片

3、緩存何時開啟?

  當開啟Mapper級別的緩存時,緩存被開啟

  緩存是一直開啟的

4、緩存何時被命中?

技術分享圖片

  5、緩存清空的時機

  ①數據庫發生變更(update,insert,delete),即使事物沒有提交,緩存

失效

  ②對於相同命名空間Mapper的緩存,多個線程,並發使用相同Mapper的不同語句,任意一個執行事物提交,可導致緩存失效

  實際效果:

  緩存 會和Mysql的rr隔離級別一致,不會導致幻讀(read uncommited)

  緩存 在不使用緩存的時候,有效

  驗證緩存

技術分享圖片

  使用代碼驗證:

  兩次查詢,只訪問了數據庫1次.第二次不再請求數據庫

  技術分享圖片  

  一次查詢,一次更新(不提交),一次查詢.緩存失效,出發了兩次數據庫查詢。

技術分享圖片

  緩存的驗證

  不配置緩存時,驗證不同的sqlSesiion緩存是否通用

  觸發2次數據庫訪問

  技術分享圖片  

  配置緩存參數

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

   技術分享圖片

  結果出乎意料,緩存竟然沒有命中。分析下原因:

   技術分享圖片

  即使打開了緩存,首先也是保存在事物級別的緩存裏,TransactionalCache裏.

  只有當實物提交時,才會真正將緩存轉移到delegate中(delegate是真正的Mapper之間公用的緩存)

  調整代碼,後緩存生效。

  技術分享圖片

  讓人不理解的,出於什麽目的,要commit後,再共享?

  如果在某一秒,有10個並發共同訪問數據庫。那他們會同時產生10個連接,並不會命中。  

6、Mybatis緩存設計的目的

  簡單,不配置也可以使用。用與在一個sqlSession中多次使用相同條件多次查詢。

7、Mybatis緩存設計的目的

  增強版,也支持事物級別的緩存,同時支持不同sqlSession之間的共享。擴大可緩存的可用性。

mybatis緩存的設計