1. Buffer Pool
用于緩存表數(shù)據(jù)與索引數(shù)據(jù)阳欲,把磁盤(pán)上的數(shù)據(jù)加載到緩沖池,避免每次訪問(wèn)都進(jìn)行磁盤(pán)IO陋率,起到加速訪問(wèn)的作用球化。
InnoDB緩沖池策略
- 按頁(yè)(4K)讀取
磁盤(pán)讀寫(xiě),并不是按需讀取瓦糟,而是按頁(yè)讀取筒愚,一次至少讀一頁(yè)數(shù)據(jù)(一般是4K),如果未來(lái)要讀取的數(shù)據(jù)就在頁(yè)中菩浙,就能夠省去后續(xù)的磁盤(pán)IO锨能,提高效率。- “集中讀寫(xiě)”的原則(預(yù)讀)
數(shù)據(jù)訪問(wèn)芍耘,通常都遵循“集中讀寫(xiě)”的原則址遇,使用一些數(shù)據(jù),大概率會(huì)使用附近的數(shù)據(jù)斋竞,這就是所謂的“局部性原理”倔约。InnoDB會(huì)把一些“可能要訪問(wèn)”的頁(yè)提前加入緩沖池,避免未來(lái)的磁盤(pán)IO操作坝初。
傳統(tǒng)LRU緩沖池算法
為了減少數(shù)據(jù)移動(dòng)浸剩,LRU一般用鏈表實(shí)現(xiàn)钾军。最常見(jiàn)的玩法是,把入緩沖池的頁(yè)放到LRU的頭部绢要,作為最近訪問(wèn)的元素吏恭,從而最晚被淘汰。這里又分兩種情況:
(1)頁(yè)已經(jīng)在緩沖池里重罪,那就只做“移至”LRU頭部的動(dòng)作樱哼,而沒(méi)有頁(yè)被淘汰;
(2)頁(yè)不在緩沖池里剿配,除了做“放入”LRU頭部的動(dòng)作搅幅,還要做“淘汰”LRU尾部頁(yè)的動(dòng)作;InnoDB并不直接使用傳統(tǒng)的LRU緩沖池算法, 因?yàn)閭鹘y(tǒng)的LRU緩沖池算法會(huì)出現(xiàn)以下問(wèn)題:
(1)預(yù)讀失效: 由于預(yù)讀(Read-Ahead)呼胚,提前把頁(yè)放入了緩沖池茄唐,但最終MySQL并沒(méi)有從頁(yè)中讀取數(shù)據(jù),稱為預(yù)讀失效蝇更。
(2)緩沖池污染: 當(dāng)某一個(gè)SQL語(yǔ)句沪编,要批量掃描大量數(shù)據(jù)時(shí),可能導(dǎo)致把緩沖池的所有頁(yè)都替換出去年扩,導(dǎo)致大量熱數(shù)據(jù)被換出漾抬,MySQL性能急劇下降,這種情況叫緩沖池污染常遂。
InnoDB對(duì)傳統(tǒng)LRU旳優(yōu)化
預(yù)讀失敗優(yōu)化 - 新老生代機(jī)制
(1)將LRU分為兩個(gè)部分:新生代(new sublist) + 老生代(old sublist)
(2)新老生代收尾相連纳令,即:新生代的尾(tail)連接著老生代的頭(head);
(3)新頁(yè)(例如被預(yù)讀的頁(yè))加入緩沖池時(shí)克胳,只加入到老生代頭部
(4)如果數(shù)據(jù)真正被讀绕郊ā(預(yù)讀成功),才會(huì)加入到新生代的頭部
(5)如果數(shù)據(jù)沒(méi)有被讀取漠另,則會(huì)比新生代里的“熱數(shù)據(jù)頁(yè)”更早被淘汰出緩沖池
新老生代機(jī)制
緩沖池污染優(yōu)化 - 老生代停留時(shí)間窗口機(jī)制
(1)假設(shè)T=老生代停留時(shí)間窗口捏雌;
(2)插入老生代頭部的頁(yè),即使立刻被訪問(wèn)笆搓,并不會(huì)立刻放入新生代頭部性湿;
(3)只有滿足“被訪問(wèn)”并且“在老生代停留時(shí)間”大于T,才會(huì)被放入新生代頭部满败;
老生代停留時(shí)間窗口機(jī)制
buffer_pool相關(guān)重要參數(shù)
- innodb_buffer_pool_size
配置緩沖池的大小肤频,在內(nèi)存允許的情況下,DBA往往會(huì)建議調(diào)大這個(gè)參數(shù)算墨,越多數(shù)據(jù)和索引放到內(nèi)存里宵荒,數(shù)據(jù)庫(kù)的性能會(huì)越好。- innodb_old_blocks_pct
老生代占整個(gè)LRU鏈長(zhǎng)度的比例,默認(rèn)是37报咳,即整個(gè)LRU中新生代與老生代長(zhǎng)度比例是63:37侠讯。- innodb_old_blocks_time
老生代停留時(shí)間窗口,單位是毫秒暑刃,默認(rèn)是1000厢漩,即同時(shí)滿足“被訪問(wèn)”與“在老生代停留時(shí)間超過(guò)1秒”兩個(gè)條件,才會(huì)被插入到新生代頭部岩臣。