Ⅰ、緩沖池介紹
InnoDB的緩沖池(buffer pool)類似于oracle的sga,里面存放數(shù)據(jù)頁(yè)、索引頁(yè)、change buffer、ahi等內(nèi)容。
每次讀寫數(shù)據(jù)都需要通過buffer pool,當(dāng)buffer pool中沒有用戶所需要的數(shù)據(jù)時(shí)則去硬盤中獲取。
?
通過緩沖池操作數(shù)據(jù)流程
innodb_buffer_pool_size參數(shù)控制緩沖池的總?cè)萘浚?.7開始的版本可以在線動(dòng)態(tài)調(diào)整該參數(shù),一般來說,越大性能越好,如果所有熱數(shù)據(jù)都能緩存到緩沖池中,那樣性能是非常可觀的。
Ⅱ、緩沖池的性能問題
2.1 性能線性擴(kuò)展
假設(shè)一臺(tái)服務(wù)器72core,ht超線程后,144個(gè)邏輯core,壓測(cè)時(shí)按道理144個(gè)core都應(yīng)該跑滿,如果跑不滿就說明并發(fā)有瓶頸,加的core用不上,性能上不去。
5.1之前的版本常常被吐槽這個(gè)問題,現(xiàn)在已經(jīng)不存在這個(gè)問題。
1G空間中有65536個(gè)頁(yè),對(duì)這些頁(yè)進(jìn)行管理,每次操作都要對(duì)緩沖池加鎖(latch,不是數(shù)據(jù)庫(kù)的lock),如果緩沖池太大了就會(huì)產(chǎn)生瓶頸。
qps達(dá)到1w,每秒鐘至少要獲取1w次latch,這里只看緩沖池的latch,忽略latch的釋放和喚醒,開銷非常大。
如何提升緩沖池性能
調(diào)整innodb_buffer_pool_instances參數(shù),設(shè)置為cpu的數(shù)量。
假設(shè)開始這個(gè)值是1,現(xiàn)調(diào)整為4,原來1個(gè)緩沖池管理65536個(gè)頁(yè),現(xiàn)在4個(gè)緩沖池,每個(gè)緩沖池管理16384個(gè)頁(yè),拆成4個(gè)分片,將熱點(diǎn)打散,latch變少了,并發(fā)性能提升了。
這是非常常見的內(nèi)核層對(duì)并發(fā)調(diào)優(yōu)的手段,經(jīng)測(cè)試,不調(diào)整與調(diào)整后性能相差30%。
注意:
設(shè)置多個(gè)緩沖池的時(shí)候,必須滿足每個(gè)池子大于1G才生效。
Ⅲ、緩沖池的管理
3.1 緩沖池的組成
?緩沖池核心組成
緩沖池中的熱點(diǎn)是以頁(yè)為單位來管理,并不是三種List加起來等于總的bp大小,而是Free List + LRU List(Flush List包含在LRU list中)。
Free List放空白的page,MySQL剛啟動(dòng)時(shí),緩沖池中有一個(gè)個(gè)16K的空白的頁(yè),這些頁(yè)存放在(鏈表串聯(lián))在Free List中。
LRU List包括LRU和unzip_LRU,當(dāng)讀取一個(gè)數(shù)據(jù)頁(yè)的時(shí)候,就從Free List中取出一個(gè)頁(yè),存入數(shù)據(jù),并將該頁(yè)放入LRU List中。
當(dāng)Free List給一個(gè)頁(yè)給LRU List時(shí),這個(gè)過程中需要一個(gè)并發(fā)控制,也就是之前說的latch。假設(shè)現(xiàn)在有兩個(gè)線程都讀到磁盤上這個(gè)頁(yè),則都需要問Free List來申請(qǐng)空閑頁(yè),誰先來先給誰,latch就是對(duì)這三個(gè)List進(jìn)行并發(fā)控制訪問的。
Flush List組織臟頁(yè)(被修改但未刷入磁盤的數(shù)據(jù)頁(yè)),根據(jù)每個(gè)臟頁(yè)的oldest_lsn進(jìn)行排序。假設(shè)被讀到的頁(yè),馬上被更新,這個(gè)頁(yè)就叫臟頁(yè),會(huì)被放入到Flush List列表中,但只是放了一個(gè)指針(page Number),而不是實(shí)際的頁(yè)