21 生產(chǎn)經(jīng)驗(yàn):如何通過多個Buffer Pool來優(yōu)化數(shù)據(jù)庫的并發(fā)性能?

生產(chǎn)經(jīng)驗(yàn):如何通過多個Buffer Pool來優(yōu)化數(shù)據(jù)庫的并發(fā)性能?
1、Buffer Pool在訪問的時(shí)候需要加鎖嗎?
前面我們已經(jīng)把Buffer Pool的整體工作原理和設(shè)計(jì)原理都已經(jīng)給大家分析的比較清楚了,基本上目前大家都能夠很好的理解,我們對MySQL執(zhí)行CRUD操作時(shí)候的第一步,就是利用Buffer Pool里的緩存來更新或者查詢。
那么既然已經(jīng)把Buffer Pool的原理都講的差不多了,接著我們就可以來給大家說說Buffer Pool在實(shí)際生產(chǎn)環(huán)境運(yùn)行中的一些經(jīng)驗(yàn),應(yīng)該如何對Buffer Pool進(jìn)行一些配置上的優(yōu)化,來提升他的訪問性能呢?
首先我們來看第一個問題,大家都知道,Buffer Pool其實(shí)本質(zhì)就是一大塊內(nèi)存數(shù)據(jù)結(jié)構(gòu),由一大堆的緩存頁和描述數(shù)據(jù)塊組成的,然后加上了各種鏈表(free、flush、lru)來輔助他的運(yùn)行。
好,那么這個時(shí)候假設(shè)MySQL同時(shí)接收到了多個請求,他自然會用多個線程來處理這多個請求,每個線程會負(fù)責(zé)處理一個請求,對吧?
然后這多個線程是不是應(yīng)該會同時(shí)去訪問Buffer Pool呢?就是同時(shí)去操作里面的緩存頁,同時(shí)操作一個free鏈表、flush鏈表、lru鏈表,是嗎?
我們看下圖,就是一個多線程并發(fā)訪問Buffer Pool的示意圖。
? ? ? ? ? ?

那么大家思考一下,現(xiàn)在多個線程來并發(fā)的訪問這個Buffer Pool了,此時(shí)他們都是在訪問內(nèi)存里的一些共享的數(shù)據(jù)結(jié)構(gòu),比如說緩存頁、各種鏈表之類的,那么此時(shí)是不是必然要進(jìn)行加鎖?
對,多線程并發(fā)訪問一個Buffer Pool,必然是要加鎖的,然后讓一個線程先完成一系列的操作,比如說加載數(shù)據(jù)頁到緩存頁,更新free鏈表,更新lru鏈表,然后釋放鎖,接著下一個線程再執(zhí)行一系列的操作。
2、多線程并發(fā)訪問加鎖,數(shù)據(jù)庫的性能還能好嗎?
既然我們已經(jīng)解決了第一個問題,就是多線程并發(fā)訪問一個Buffer Pool的時(shí)候必然會加鎖,然后很多線程可能要串行著排隊(duì),一個一個的依次執(zhí)行自己要執(zhí)行的操作,那么此時(shí)我問大家第二個問題,此時(shí)數(shù)據(jù)庫的性能還能好嗎?
應(yīng)該這么說,即使就一個Buffer Pool,即使多個線程會加鎖串行著排隊(duì)執(zhí)行,其實(shí)性能也差不到哪兒去。
因?yàn)榇蟛糠智闆r下,每個線程都是查詢或者更新緩存頁里的數(shù)據(jù),這個操作是發(fā)生在內(nèi)存里的,基本都是微秒級的,很快很快,包括更新free、flush、lru這些鏈表,他因?yàn)槎际腔阪湵磉M(jìn)行一些指針操作,性能也是極高的。
所以即使每個線程排隊(duì)加鎖,然后執(zhí)行一系列操作,數(shù)據(jù)庫的性能倒也是還可以的。
但是再怎么可以,你畢竟也是每個線程加鎖然后排隊(duì)一個一個操作,這也不是特別的好,特別是有的時(shí)候你的線程拿到鎖之后,他可能要從磁盤里讀取數(shù)據(jù)頁加載到緩存頁里去,這還發(fā)生了一次磁盤IO呢!所以他要是進(jìn)行磁盤IO的話,也許耗時(shí)就會多一些,那么后面排隊(duì)等他的線程自然就多等一會兒了!
3、MySQL的生產(chǎn)優(yōu)化經(jīng)驗(yàn):多個Buffer Pool優(yōu)化并發(fā)能力
因此這里我們給大家介紹一個MySQL的生產(chǎn)環(huán)境優(yōu)化經(jīng)驗(yàn),就是可以給MySQL設(shè)置多個Buffer Pool來優(yōu)化他的并發(fā)能力。
一般來說,MySQL默認(rèn)的規(guī)則是,如果你給Buffer Pool分配的內(nèi)存小于1GB,那么最多就只會給你一個Buffer Pool。
但是如果你的機(jī)器內(nèi)存很大,那么你必然會給Buffer Pool分配較大的內(nèi)存,比如給他個8G內(nèi)存,那么此時(shí)你是同時(shí)可以設(shè)置多個Buffer Pool的,比如說下面的MySQL服務(wù)器端的配置。
[server]
innodb_buffer_pool_size = 8589934592
innodb_buffer_pool_instances = 4
我們給buffer pool設(shè)置了8GB的總內(nèi)存,然后設(shè)置了他應(yīng)該有4個Buffer Pool,此時(shí)就是說,每個buffer pool的大小就是2GB
這個時(shí)候,MySQL在運(yùn)行的時(shí)候就會有4個Buffer Pool了!每個Buffer Pool負(fù)責(zé)管理一部分的緩存頁和描述數(shù)據(jù)塊,有自己獨(dú)立的free、flush、lru等鏈表。
這個時(shí)候,假設(shè)多個線程并發(fā)過來訪問,那么不就可以把壓力分散開來了嗎?有的線程訪問這個buffer pool,有的線程訪問那個buffer pool。
我們看下圖:
? ? ? ? ? ?

? ? ??
所以這樣的話,一旦你有了多個buffer pool之后,你的多線程并發(fā)訪問的性能就會得到成倍的提升,因?yàn)槎鄠€線程可以在不同的buffer pool中加鎖和執(zhí)行自己的操作,大家可以并發(fā)來執(zhí)行了!
所以這個在實(shí)際生產(chǎn)環(huán)境中,設(shè)置多個buffer pool來優(yōu)化高并發(fā)訪問性能,是mysql一個很重要的優(yōu)化技巧。
End
專欄版權(quán)歸公眾號儒猿技術(shù)窩所有
未經(jīng)許可不得傳播,如有侵權(quán)將追究法律責(zé)任