天天看點

MySQL · 源碼分析 · InnoDB LRU List刷髒改進之路

在MySQL中,如果目前資料庫需要操作的資料集比Buffer pool中的空閑頁面大的話,目前Buffer pool中的資料頁就必須進行髒頁淘汰,以便騰出足夠的空閑頁面供目前的查詢使用。如果資料庫負載太高,對于空閑頁面的需求超出了page cleaner的淘汰能力,這時候是否能夠快速擷取空閑頁面,會直接影響到資料庫的處理能力。我們将從下面三個階段來看一下MySQL以及Percona對LRU List刷髒的改進過程。

衆所周知,MySQL操作任何一個資料頁面都需要讀到Buffer pool進行才會進行操作。是以任何一個讀寫請求都需要從Buffer pool來擷取所需頁面。如果需要的頁面已經存在于Buffer pool,那麼直接利用目前頁面進行操作就行。但是如果所需頁面不在Buffer pool,比如UPDATE操作,那麼就需要從Buffer pool中新申請空閑頁面,将需要讀取的資料放到Buffer pool中進行操作。那麼官方MySQL 5.7.4之前的版本如何從buffer pool中擷取一個頁面呢?請看如下代碼段:

從上面擷取一個空閑頁的源碼邏輯可以看出,buf_LRU_get_free_block會循環嘗試去淘汰LRU list上的頁面。每次循環都會去通路free list,檢視是否有足夠的空閑頁面。如果沒有将繼續從LRU list去淘汰。這樣的循環在負載比較高的情況下,會加劇對free list以及LRU list的mutex競争。

MySQL空閑頁面的擷取依賴于page cleaner的重新整理能力,如果page cleaner不能即時的重新整理足夠的空閑頁面,那麼系統就會使用上面的邏輯來為使用者線程申請空閑頁面。但如果讓page cleaner加快重新整理,又會導緻頻繁重新整理髒資料,引發性能問題。 為了改善系統負載太高的情況下,page cleaner刷髒能力不足,進而使用者線程調用LRU刷髒導緻鎖競争加劇影響資料庫性能,Percona對此進行了改善,引入獨立的線程負責LRU list的刷髒。目的是為了讓獨立線程根據系統負載動态調整LRU的刷髒能力。由于LRU list的刷髒從page cleaner線程中脫離出來,調整LRU list的刷髒能力不再會影響到page cleaner。下面我們看一下相關的源碼:

從上面的源碼可以看到,LRU list的刷髒依賴于LRU_mangager_thread, 當然正常的page cleaner也會對LRU list進行刷髒。但是整個Buffer pool的所有instances都依賴于一個LRU list刷髒線程,負載比較高的情況下也很有可能成為瓶頸。

官方MySQL 5.7版本為了緩解單個page cleaner線程進行刷髒的壓力,在5.7.4中引入了multiple page cleaner threads這個feature,用來增強刷髒速度,但是從下面的測試可以發現,即便是multiple page cleaner threads在高負載的情況下,還是會對系統性能有影響。下面的測試結果也顯示了性能方面受到的影響。

MySQL · 源碼分析 · InnoDB LRU List刷髒改進之路

就multiple page cleaner刷髒能力受到限制,主要是因為存在以下問題:

1) LRU List刷髒在先,Flush list的刷髒在後,但是是互斥的。也就是說在進Flush list刷髒的時候,LRU list不能繼續去刷髒,必須等到下一個循環周期才能進行。

2) 另外一個問題就是,刷髒的時候,page cleaner coodinator會等待所有的page cleaner線程完成之後才會繼續響應刷髒請求。這帶來的問題就是如果某個buffer pool instance比較熱的話,page cleaner就不能及時進行響應。

針對上面的問題,Percona改進了原來的單線程LRU list刷髒的方式,繼續将LRU list獨立于page cleaner threads并将LRU list單線程刷髒增加為多線程刷髒。page cleaner隻負責flush list的刷髒,lru_manager_thread隻負責LRU List刷髒。這樣的分離,可以使得LRU list刷髒和Flush List刷髒并行執行。看一下修改之後的測試情況:

MySQL · 源碼分析 · InnoDB LRU List刷髒改進之路

下面用Multiple LRU list flush threads的源碼patch簡單介紹一下Percona所做的更改。

綜上所述,本篇文章主要從源碼層面對Percona以及官方對于LRU list刷髒方面所做的改進進行了分析。Percona對于LRU list刷髒問題做了很大的貢獻。從測試結果可以看到,如果負載較高,空閑頁不足的情況下,Percona的改進起到了明顯的作用。