記得點(diǎn)擊"歡少的成長(zhǎng)之路",設(shè)為星標(biāo)?
后臺(tái)點(diǎn)擊【聯(lián)系我】,申請(qǐng)加入優(yōu)質(zhì)技術(shù)學(xué)習(xí)社群
(相關(guān)資料圖)
大家好,我是Leo。
好久沒(méi)有輸出技術(shù)理論了,實(shí)在是忙。最近主要以設(shè)計(jì)系統(tǒng)為主了。面試剛好又倒在了Mybatis原理。今天來(lái)聊一下Mybatis的一級(jí)緩存,二級(jí)緩存。
Mybatis緩存是內(nèi)存中的數(shù)據(jù),主要是對(duì)數(shù)據(jù)庫(kù)查詢結(jié)果的保存,使用緩存的好處是避免頻繁與數(shù)據(jù)庫(kù)進(jìn)行交互,提升查詢的響應(yīng)速度。
數(shù)據(jù)庫(kù)緩存擴(kuò)展聊到Mybatis緩存。我們可以擴(kuò)展聊一下MySQL緩存。MySQL緩存其實(shí)與Mybatis類似,在查詢的時(shí)候都會(huì)先通過(guò)查詢緩存檢查一下所需的數(shù)據(jù)是否存在緩存中,如果存在緩存的話就會(huì)直接返回,這樣就達(dá)到了避免頻繁與數(shù)據(jù)庫(kù)進(jìn)行交互的目的。
數(shù)據(jù)查詢流程圖
回歸正題在學(xué)習(xí)過(guò)程中,希望大家把知識(shí)點(diǎn)串起來(lái)學(xué)習(xí),這樣有助力更好的學(xué)習(xí)與理解
Mybatis 緩存主要分一級(jí)緩存和二級(jí)緩存。
一級(jí)緩存一級(jí)緩存也稱為本地緩存(SqlSession),屬于二級(jí)緩存的子集。與數(shù)據(jù)庫(kù)同一次會(huì)話期間查詢到的數(shù)據(jù)會(huì)放在本地緩存中。以后如果需要獲取相同的數(shù)據(jù),直接從緩存中拿,沒(méi)必要再去查詢數(shù)據(jù)庫(kù)。
一級(jí)緩存的緩存數(shù)據(jù)只在SqlSession內(nèi)有效,它的范圍有兩種SESSION和STATEMENT,默認(rèn)是SESSION。如果不想使用一級(jí)緩存,可以通過(guò)下列代碼配置
使用SESSION,這樣每次執(zhí)行完一個(gè)Mapper中的語(yǔ)句都會(huì)將一級(jí)緩存清除。二級(jí)緩存
一級(jí)緩存作用域太低,如果多個(gè)SqlSession需要共享緩存,則就需要開(kāi)啟二級(jí)緩存。二級(jí)緩存也叫全局緩存,二級(jí)緩存是基于namespace級(jí)別的緩存,一個(gè)namespace對(duì)應(yīng)一個(gè)二級(jí)緩存。二級(jí)緩存需要我們手動(dòng)開(kāi)啟。
我們可以通過(guò)在 mybatis-config 文件中配置開(kāi)啟二級(jí)緩存。
查詢順序
Mybatis的查詢順序如下圖
Mybatis查詢順序
我們可以根據(jù)上圖大概介紹一下B的流程。
首先創(chuàng)建SqlSession會(huì)話查詢一條數(shù)據(jù),這條數(shù)據(jù)就會(huì)被放到當(dāng)前會(huì)話的一級(jí)緩存中。如果當(dāng)前SqlSession去執(zhí)行commit操作(插入,更新,刪除),那么就會(huì)清空SqlSession中的一級(jí)緩存,保證緩存中始終保存的是最新的數(shù)據(jù),避免臟讀。這個(gè)時(shí)候并不會(huì)把一級(jí)緩存更新到二級(jí)緩存,這一步操作是在關(guān)閉SqlSession時(shí)觸發(fā)的。新會(huì)話查詢信息,就會(huì)從二級(jí)緩存中獲取數(shù)據(jù)。注意:兩次查詢必須在同一個(gè)SqlSession中完成,否則將不會(huì)走M(jìn)ybatis的一級(jí)緩存
相反,我們?cè)谑褂肕ybatis作為我們的持久層框架時(shí),也就是上圖的A流程
開(kāi)啟二級(jí)緩存后,會(huì)使用 CachingExecutor 裝飾 Executor進(jìn)入一級(jí)緩存查詢流程前先在CachingExecutor進(jìn)行二級(jí)緩存的查詢?nèi)绻?jí)緩存沒(méi)有命中的話會(huì)到一級(jí)緩存中查詢最后一級(jí)緩存沒(méi)有的話才會(huì)去與數(shù)據(jù)庫(kù)進(jìn)行查詢交互生命周期二級(jí)緩存開(kāi)啟后,同一個(gè) namespace 下的所有操作語(yǔ)句,都影響著同一個(gè) Cache,即二級(jí)緩存被多個(gè) SqlSession 共享,是一個(gè)全局的變量。
MyBatis 是默認(rèn)關(guān)閉二級(jí)緩存的,因?yàn)閷?duì)于增刪改操作頻繁的話,那么二級(jí)緩存形同虛設(shè),每次都會(huì)被清空緩存。
一級(jí)緩存沒(méi)有過(guò)期時(shí)間,只有生命周期。MyBatis在開(kāi)啟一個(gè)數(shù)據(jù)庫(kù)會(huì)話時(shí),會(huì)創(chuàng)建一個(gè)新的SqlSession對(duì)象,SqlSession對(duì)象中會(huì)有一個(gè)Executor對(duì)象,Executor對(duì)象中持有一個(gè)PerpetualCache對(duì)象。當(dāng)會(huì)話結(jié)束時(shí),SqlSession對(duì)象及其內(nèi)部的Executor對(duì)象還有PerpetualCache對(duì)象也一并釋放掉。
二級(jí)緩存有過(guò)期時(shí)間,但沒(méi)有后臺(tái)線程進(jìn)行檢測(cè)。需要注意的是,并不是key-value的過(guò)期時(shí)間,而是這個(gè)cache的過(guò)期時(shí)間,是flushInterval,意味著整個(gè)清空緩存cache,所以不需要后臺(tái)線程去定時(shí)檢測(cè)。每當(dāng)存取數(shù)據(jù)的時(shí)候,都有檢測(cè)一下cache的生命時(shí)間,默認(rèn)是1小時(shí),如果這個(gè)cache存活了一個(gè)小時(shí),那么將整個(gè)清空一下。