日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 运维知识 > 数据库 >内容正文

数据库

MySQL - InnoDB特性 - Buffer Pool漫谈

發(fā)布時間:2023/12/3 数据库 31 豆豆
生活随笔 收集整理的這篇文章主要介紹了 MySQL - InnoDB特性 - Buffer Pool漫谈 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

轉(zhuǎn)載自??MySQL - InnoDB特性 - Buffer Pool漫談

緩存管理是DBMS的核心系統(tǒng),用于管理數(shù)據(jù)頁的訪問、刷臟和驅(qū)逐;雖然操作系統(tǒng)本身有page cache,但那不是專門為數(shù)據(jù)庫設(shè)計(jì)的,所以大多數(shù)數(shù)據(jù)庫系統(tǒng)都是自己來管理緩存。由于幾乎所有的數(shù)據(jù)頁訪問都涉及到Buffer Pool,因此buffer pool的并發(fā)訪問控制尤為重要,可能會影響到吞吐量和響應(yīng)時間,本文主要回顧一下MySQL的buffer Pool最近幾個版本的發(fā)展(若有遺漏,歡迎評論補(bǔ)充), 感受下最近幾年這一塊的進(jìn)步

MySQL5.5之前

只能設(shè)置一個buffer pool, 通過innodb_buffer_pool_size來控制, 刷臟由master線程承擔(dān),擴(kuò)展性差。

?

MySQL 5.5

引入?yún)?shù)innodb_buffer_pool_instances,將buffer pool拆分成多個instance,從而減少對buffer pool的訪問控制,這時候的刷臟還是由Master線程來承擔(dān)。

?

MySQL 5.6

引入了buffer Pool page Id轉(zhuǎn)儲和導(dǎo)入特性,也就是說可以隨時把內(nèi)存中的page no存下來到文件里,在重啟時會自動把這些Page加載到內(nèi)存中,使內(nèi)存保持warm狀態(tài). 此外該版本第一次引入了page cleaner,將flush list/lru上的刷臟驅(qū)逐工作轉(zhuǎn)移到單獨(dú)線程,減少了master線程的負(fù)擔(dān)

?

MySQL 5.7

這個版本發(fā)布了一個重要特性:online buffer pool resize. 當(dāng)然是否是online需要打一個問號,因?yàn)樵趓esize的過程中需要拿很多全局大鎖,在高負(fù)載場景下很容易導(dǎo)致實(shí)例Hang住(81615)。?
和之前不同,buffer pool被分成多個instance,每個instance又由多個chunk組成,每個chunk的大小受到參數(shù)innodb_buffer_pool_chunk_size控制,默認(rèn)128MB, buffer pool resize都是以chunk為單位增加或減少的。
另外一個需要注意的點(diǎn)是:你配置的Buffer Pool Size可能比你實(shí)際使用的內(nèi)存要大,尤其對于大Bp而言,這是因?yàn)閮?nèi)部做了對齊處理, buffer pool size必須以 innodb_buffer_pool_chunk_size * innodb_buffer_pool_instances來做向上對齊(80350)

我們知道通常數(shù)據(jù)文件的IO都被設(shè)置成O_DIRECT, 但每次修改后依然需要去做fsync,來持久化元數(shù)據(jù)信息,而對于某些文件系統(tǒng)而言是沒必要做fsync的,因此加入了新選項(xiàng)O_DIRECT_NO_FSYNC,這個需求來自于facebook. 他們也對此做了特殊處理:除非文件size變化,否則不做fsync。(最近在buglist上對這個參數(shù)是否安全的討論也很有意思,官方文檔做了新的說明,感興趣的可以看看 [94912:O_DIRECT_NO_FSYNC possible write hole
](https://bugs.mysql.com/bug.php?id=94912))

再一個重要功能是終于引入了multiple page cleaner, 可以多個后臺線程并發(fā)刷臟頁,提供了更好的刷臟性能,有效避免用戶線程進(jìn)入single page flush。當(dāng)然這還不夠完美,主要有四點(diǎn):

  • 用戶線程依然會進(jìn)入single page flush,而一旦大量線程進(jìn)入,就會導(dǎo)致嚴(yán)重性能下降:超頻繁的fsync,激烈的dblwr競爭,線程切換等等
  • 當(dāng)redo空間不足時,用戶線程也會進(jìn)入page flush,這在高負(fù)載場景下是很常見的,你會發(fā)現(xiàn)系統(tǒng)運(yùn)行一段時間后,性能急劇下降。這是因?yàn)閞edo產(chǎn)生太快,而page flush又跟不上,導(dǎo)致checkpoint無法推進(jìn)。那么用戶線程可能就要過來做fuzzy checkpoint了。那時候性能基本上沒法看了。
  • dblwr成為重要的單點(diǎn)瓶頸。 如果你的服務(wù)器不支持原子寫的話,必須打開double write buffer。寫入Ibdata一段固定區(qū)域,這里是有鎖包含的,區(qū)分為兩部分:single page flush和batch flush, 但無論如何,即使拆分了多個page cleaner,最終擴(kuò)展性還是受限于dblwr
  • 沒有專用的lru evict線程,都是Page cleaner鍵值的。舉個簡單的例子,當(dāng)buffer pool占滿,同時又有很多臟頁時,Page cleaner可能忙于刷臟,而用戶線程則得不到free page,從而陷入single page flush
  • 如果你對上述幾個問題極不滿意,可以嘗試percona server, 他們向來擅長優(yōu)化Io bound場景的性能,并且上述幾個問題都解決了,尤其是dblwr,他們做了多分區(qū)的改進(jìn)。

    ?

    MySQL 8.0

    增加了一個功能,可以在實(shí)例宕機(jī)時,core文件里不去掉buffer pool, 這大大減少了core文件的大小。要知道,很多時候?qū)嵗龗焓且驗(yàn)槲募p壞,不停的core重啟會很快把磁盤占滿,你可以通過設(shè)置參數(shù)innodb_buffer_pool_in_core_file來控制。

    另外8.0最重要的一個改進(jìn)就是:終于把全局大鎖buffer pool mutex拆分了,各個鏈表由其專用的mutex保護(hù),大大提升了訪問擴(kuò)展性。實(shí)際上這是由percona貢獻(xiàn)給上游的,而percona在5.5版本就實(shí)現(xiàn)了這個特性(WL#8423: InnoDB: Remove the buffer pool mutex?以及?bug#75534)。

    原來的一個大mutex被拆分成多個為free_list, LRU_list, zip_free, 和zip_hash單獨(dú)使用mutex:

    - LRU_list_mutex for the LRU_list;- zip_free mutex for the zip_free arrays;- zip_hash mutex for the zip_hash hash and in_zip_hash flag;- free_list_mutex for the free_list and withdraw list.- flush_state_mutex for init_flush, n_flush, no_flush arrays.

    由于log system采用lock-free的方式重新實(shí)現(xiàn),flush_order_mutex也被移除了,帶來的后果是flush list上部分page可能不是有序的,進(jìn)而導(dǎo)致checkpoint lsn和以前不同,不再是某個log record的邊界,而是可能在某個日志的中間,給崩潰恢復(fù)帶來了一定的復(fù)雜度(需要回溯日志)

    log_free_check也發(fā)生了變化,當(dāng)超出同步點(diǎn)時,用戶線程不再自己去做preflush,而是通知后臺線程去做,自己在那等待(log_request_checkpoint), log_checkpointer線程會去考慮log_consider_sync_flush,這時候如果你打開了參數(shù)innodb_flush_sync的話, 那么flush操作將由page cleaner線程來完成,此時page cleaner會忽略io capacity的限制,進(jìn)入激烈刷臟

    8.0還增加了一個新的參數(shù)叫innodb_fsync_threshold,,例如創(chuàng)建文件時,會設(shè)置文件size,如果服務(wù)器有多個運(yùn)行的實(shí)例,可能會對其他正常運(yùn)行的實(shí)例產(chǎn)生明顯的沖擊。為了解決這個問題,從8.0.13開始,引入了這個閾值,代碼里在函數(shù)os_file_set_size注入,這個函數(shù)通常在創(chuàng)建或truncate文件之類的操作時調(diào)用,表示每寫到這么多個字節(jié)時,要fsync一次,避免對系統(tǒng)產(chǎn)生沖擊。這個補(bǔ)丁由facebook貢獻(xiàn)給上游。

    ?

    其他

    當(dāng)然也有些輔助結(jié)構(gòu)來快速查詢buffer pool:

    • adaptive hash index: 直接把葉子節(jié)點(diǎn)上的記錄索引了,在滿足某些條件時,可以直接定位到葉子節(jié)點(diǎn)上,無需從根節(jié)點(diǎn)開始掃描,減少讀的page個數(shù)
    • page hash: 每個buffer pool instance上都通過輔助的page hash來快速訪問其中存儲的page,讀加s鎖,寫入新page加x鎖。page hash采用分區(qū)的結(jié)構(gòu),默認(rèn)為16,有一個參數(shù)innodb_page_hash_locks,但很遺憾,目前代碼里是debug only的,如果你想配置這個參數(shù),需要稍微修改下代碼,把參數(shù)定義從debug宏下移出來
    • change buffer: 當(dāng)二級索引頁不在時,可以把操作緩存到ibdata里的一個btree(ibuf)中,下次需要讀入這個page時,再做merge;另外后臺master線程會也會嘗試merge ibuf。

    最后,聽說官方正在努力解決double write buffer的瓶頸問題,期待一下.

    創(chuàng)作挑戰(zhàn)賽新人創(chuàng)作獎勵來咯,堅(jiān)持創(chuàng)作打卡瓜分現(xiàn)金大獎

    總結(jié)

    以上是生活随笔為你收集整理的MySQL - InnoDB特性 - Buffer Pool漫谈的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。