週末在一臺MySQL實例上頻繁作大批量的寫入測試,無心中發現MySQL的errorlog中頻繁出現以下的Note:
page_cleaner: 1000ms intended loop took **** ms. The settings might not be optimal. (flushed=**** and evicted=0, during the time.)html
一個典型的信息以下async
InnoDB: page_cleaner: 1000ms intended loop took 4068ms. The settings might not be optimal. (flushed=2000 and evicted=0, during the time.)
該告警意味着MySQL實例按照目前IO相關的參數配置的前提下,存在着IO寫入性能上的瓶頸,配置參數與IO處理能力不匹配。
由於很清楚是在作測試的狀況下,連續大批量寫入數據形成的,頗有多是checkpoint刷新髒頁形成IO不足的警告。oop
page_cleaner超時只是果,而不是因,一個果多是有不一樣的因形成的,具體緣由在哪裏?
逐步反推這個過程:單次刷新內存數據到磁盤的數量過大<----LRU刷新或者髒頁刷刷新<------大批量讀寫數據(LRU)或者刪除出數據(delete,drop等等))。
另一個緣由(刪除數據形成的page_cleaner超時)參考:http://www.javashuo.com/article/p-cxwgzpxp-en.html性能
MySQL在正常運行時4個與IO寫入(checkpoint)相關的參數,而後逐一分析其寫入的時機和內存頁面的數量。測試
1,innodb_io_capacity優化
master thread中每秒或者每10s循環中刷新髒頁的數量spa
那麼master thread中定時循環刷新髒頁的數據是多少?由參數innodb_io_capacity決定,如下截圖自《MySQL技術內幕InnoDB存儲引擎》page 41.net
2,innodb_max_dirty_pages_pct線程
innodb buffer pool中髒頁數量超過這個比例以後,刷新部分髒頁到磁盤。日誌
這種狀況下刷新的「部分」髒頁,究竟是刷新多少個髒頁?
由於沒有閱讀源碼的能力,從這裏來看(後面會給出參考連接),這個值是依舊是innodb_io_capacity個髒頁。
innodb_max_dirty_pages_pct這個參數自己(75%)默認值差很少就是最優化的,應該是不能瞎調的。如下截圖自《MySQL技術內幕InnoDB存儲引擎》page 42
3,innodb_lru_scan_depth
lru列表中保持空閒page的數據量,若是低於這個數量,則按照LRU的原則刷新髒頁到磁盤。
這種狀況下是刷線多少個髒頁?
(20190906補充:這句話是有問題的的,LRU的刷新跟髒頁是沒有必然關係,LRU只是髒冷數據從bufferpool中移除掉)LRU只關心頁的冷熱程度,而不關係頁是否爲髒頁。
此狀況下觸發,默認掃描innodb_lru_scan_depth個lru冷端數據頁,將髒頁(掃描到的innodb_lru_scan_depth個冷數據頁面中,若是是髒頁的話)寫入磁盤(有10個就刷10,有100個就刷100個……)
這一點參考這個(筆者並無找到確切的證據):http://www.javashuo.com/article/p-vjbnpazl-bn.html
4,redo log日誌空間達到配置閾值的刷新(一個實例的redo log空間總和)
單個redo log大小的參數:innodb_log_file_size
redo log 個數:innodb_log_files_in_group
async_water_mark = 75%*innodb_log_file_size
sync_water_mark = 90%*innodb_log_file_size
1)當checkpoint_age<sync_water_mark的時候,無需執行Flush checkpoint。也就說,redo log剩餘空間超過25%的時候,無需執行Async/Sync Flush checkpoint。
2)當async_water_mark<checkpoint_age<sync_water_mark的時候,執行Async Flush checkpoint,也就說,redo log剩餘空間不足25%,可是大於10%的時候,執行Async Flush checkpoint,刷新到知足條件1
3)當checkpoint_age>sync_water_mark的時候,執行sync Flush checkpoint。也就說,redo log剩餘空間不足10%的時候,執行Sync Flush checkpoint,刷新到知足條件1。
在buffer pool遠沒有達到分配值的狀況下,innodb_max_dirty_pages_pct和innodb_lru_scan_depth也不會達到checkpoint的條件,redo log也沒有切換,
所以只能判定爲master thread 後臺線程定時刷新髒頁形成的IO負擔過載,所以嘗試 set global innodb_io_capacity = 1000;
經後繼續測試觀察,還沒有發現相似新的page_cleaner告警日誌產生。
參考:
http://blog.itpub.net/26506993/viewspace-2214703/
http://www.javashuo.com/article/p-vjbnpazl-bn.html
https://www.jianshu.com/p/6991304a8e26?tdsourcetag=s_pcqq_aiomsg
https://www.jianshu.com/p/ddb24f9afae0?tdsourcetag=s_pcqq_aiomsg