mysql innodb page_MySQL:Innodb page clean 线程 (一) 基础
本文為學習筆記,有誤請指出。本文第一分部為基礎部分第二部分為解析部分涉及部分源碼淺析。
本文使用源碼版本:Percona 5.7.14
本文約定
-協調工作線程:因為page clean線程的協調線程也會完成部分刷新工作,所以叫做協調工作線程。
一、page clean線程概念
Innodb中page clean線程將臟數據寫入到磁盤,臟數據寫盤后相應的redo就可以覆蓋,然后達到redo循環使用的目的。在5.7中參數可以開啟多個page clean線程服務于多個innodb buffer實例如下:
The?innodb_page_cleaners?default?value?was
changed?from?1?to?4?in?MySQL?5.7.?If?the?number?of?page?cleaner?threads?exceeds?the?numberof?buffer?pool?instances,?innodb_page_cleaners?is?automatically?set?to?the?same?value?asinnodb_buffer_pool_instances.
實際上在內部實現中如果page clean線程為4個那么包含一個協調工作線程和三個工作線程,這個協調工作線程也要完成一部分工作。在MySQL中我們可以通過語句查看到這些工作線程:
|?????17?|????????57982?|?innodb/page_cleaner_thread??????|????NULL?|?BACKGROUND?|?NULL???|?NULL?????????||?????18?|????????57983?|?innodb/page_cleaner_thread??????|????NULL?|?BACKGROUND?|?NULL???|?NULL?????????||?????19?|????????57984?|?innodb/page_cleaner_thread??????|????NULL?|?BACKGROUND?|?NULL???|?NULL?????????||?????20?|????????57985?|?innodb/page_cleaner_thread??????|????NULL?|?BACKGROUND?|?NULL???|?NULL?????????|
實際上在我淺析分析中發現,所有的工作線程都是不斷輪序每一個和buffer instance對應的槽(slot),直到所有的buffer instance都已經進行了刷臟工作為止,并沒有固定那個工作線程服務于那個buffer instance實例。
二、刷新方式
總的來說page clean線程刷新的方式分為三種如下:
1、 活躍刷新
一般來講我們線上的數據庫一般都處于活躍狀態,只要有DML/DDL等用到語句都會處于活躍狀態,但是SELECT不包含在活躍狀態下。這種狀態下刷新會開啟一個協調工作線程和多個工作線程同時工作,這種狀態其刷新的塊數算法為(page_cleaner_flush_pages_recommendation函數):
(根據參數計算出來的頁數量 +以往每秒刷新頁的數量+根據target lsn 計算出來的一個需要刷新的塊數)/3
實際上這里需要關注的就是(根據參數計算出來的頁數量),算法大概如下(af_get_pct_for_dirty函數):
如果innodb_max_dirty_pages_pct_lwm沒有開:
如果臟數據比率大于等于innodb_max_dirty_pages_pct的設置:
則返回100%
如果innodb_max_dirty_pages_pct_lwm開啟:
如果臟數據比率大于等于innodb_max_dirty_pages_pct_lwm:
則返回(臟數據比率*100)/(innodb_max_dirty_pages_pct+1)這樣一個百分比
我們計上面的百分比為A,除了百分比A還和innodb_adaptive_flushing、innodb_adaptive_flushing_lwm計算出來的百分比有關,我們記做B(af_get_pct_for_lsn函數計算),但是由于參數innodb_cleaner_lsn_age_factor默認設置為high_checkpoint,所以這個百分比比較小,具體算法見后文,其最后取值
根據參數計算出來的頁數量 = MAX(A,B)*innodb_io_capacity
2、空閑刷新
一般情況下除了活躍刷新就是空閑刷新,空閑的情況下因為服務器IO應該比較空閑,所以Innodb使用協調工作線程本身進行刷新,刷新的塊數計算比較簡單就是innodb_io_capacity設置的值。
3、 同步刷新
同步刷新則是堵塞刷新,所有需要寫臟數據庫的用戶線程都會堵塞,這是很嚴重的情況。在checkpoint的時候
會檢查或者DML語句執行過程中都會檢查redo是否處于一個安全的位置,這是調用log_free_check函數進行,如果認為臟的塊數太多,redo已經處于不安全的位置(log_checkpoint_margin),那么同步刷新會被喚醒。
關于這部分在源碼部分還會提到。
三、關于一個警告
警告如下:
page_cleaner:?1000ms??intended?loop?took?**ms.?The?settings?might?not?be?optimal.((flushed="**"?,?during?the?time.)
實際上這個警告來自于兩次刷新時間的檢測:
本次刷新時間 - 上次刷新時間 > 1秒(睡眠時間)+3秒 則報警告
這個警告一般是IO能力不足,或者參數不夠優化的結果,有了上面的基礎我們知道這里應該做如下操作:
innodb_io_capacity 應該降低
innodb_max_dirty_pages_pct 應該降低
innodb_max_dirty_pages_pct_lwm 如果設置了應該考慮降低
innodb_io_capacity_max 考慮降低涉及到上面說的百分比B的計算(af_get_pct_for_lsn函數)
降低的目的在于減少每次刷新的量,讓每次刷新塊數更加平均。從而避免page clean 線程爆發性的刷新臟數據庫,從而堵塞IO通道。如果慢慢調整后還是不行則考慮IO確實扛不住了。
關于這部分在源碼部分還會提到。
后文將會對得到這些結論的源碼進行解析。
作者微信:
微信.jpg
總結
以上是生活随笔為你收集整理的mysql innodb page_MySQL:Innodb page clean 线程 (一) 基础的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 兵马俑一号坑发掘最新成果出炉:出土千余件
- 下一篇: mysql 缓存监控_MySql 缓存查