MySQL5.7:PageCleaner的刷髒問題
之前我已經寫過一篇部落格,討論過在flush LRU_LIST/FLUSH_LIST時,5.7對其做的優化,總的來說,就是使用類似Hazard Pointer的方式,避免在flush的過程中重複掃描LIST,將時間複雜度從O(N*N)下降到了O(N)。有興趣的同學可以翻閱下這篇部落格:http://mysqllover.com/?p=1031
本文的目的主要是補充下5.7目前所做的多個page cleaner的實現思路,社群相關的bug討論,以及我近期對page cleaner所做的一些優化工作。
支援多個Page cleaner
為了提升擴充套件性和刷髒效率,在5.7.4版本里引入了多個page cleaner執行緒。從而達到並行刷髒的效果。
在該版本中,Page cleaner並未和buffer pool繫結,其模型為一個協調執行緒 + 多個工作執行緒,協調執行緒本身也是工作執行緒。因此如果innodb_page_cleaners設定為8,那麼就是一個協調執行緒,加7個工作執行緒
協調執行緒的入口函式為buf_flush_page_cleaner_coordinator
工作執行緒的入口函式為buf_flush_page_cleaner_worker
在啟動時會初始化一個slot陣列,大小為buffer pool instance的個數(buf_flush_page_cleaner_init)。
協調執行緒在決定了需要flush的page數和lsn_limit後,會設定slot陣列,將其中每個slot的狀態設定為PAGE_CLEANER_STATE_REQUESTED, 並設定目標page數及lsn_limit,然後喚醒worker執行緒 (pc_request)
worker執行緒被喚醒後,從slot陣列中取一個未被佔用的slot,修改其狀態,表示已被排程,然後對該slot所對應的buffer pool instance進行操作。
為了支援對單個bp instance進行LRU/FLUSH_LIST的重新整理,對原有程式碼做了大量的改動,worker執行緒可以直接呼叫buf_flush_LRU_list 及buf_flush_do_batch 指定buffer pool進行flush操作。 互相之間不干擾,因此可以並行刷髒。 改動整體而言比較簡單。
由於當前版本page cleaner是不和buffer pool繫結的,因此,最好不要將page cleaner的個數設定的大於buffer pool instance的個數。
如果當前例項不活躍,即沒有負載時,則單獨由協調執行緒做100%的刷髒。
worklog:
http://dev.mysql.com/worklog/task/?id=6642
程式碼比較簡單,不展開闡述,感興趣的可以讀讀補丁:
http://bazaar.launchpad.net/~mysql/mysql-server/5.7/revision/7189
http://bazaar.launchpad.net/~mysql/mysql-server/5.7/revision/7244
進一步改進Multi Page Cleaner
在MySQL 5.7.5裡進一步改進了multi page cleaner特性,讓其支援在crash recovery和shutdown時能夠應用多個page cleaner特性,來加快崩潰恢復和關閉例項的速度。
實現方式也比較簡單,例如對於recovery過程中,如果需要刷髒時,不主動刷髒,而是喚醒page cleaner,然後等待page cleaner完成。
PATCH:
http://bazaar.launchpad.net/~mysql/mysql-server/5.7/revision/8489
http://bazaar.launchpad.net/~mysql/mysql-server/5.7/revision/8522
http://bazaar.launchpad.net/~mysql/mysql-server/5.7/revision/8532
社群相關BUG
http://bugs.mysql.com/bug.php?id=68481
期望允許page cleaner做furious flush,而不是每秒做一次,對於寫入負載很猛的場景,很容易到達同步checkpoint點
http://bugs.mysql.com/bug.php?id=70500
不管是否active,總是做LRU FLUSH。 因為在某些場景下,可能沒什麼使用者負載,checkpoint age很低,但諸如purge操作需要很多free page時, 這時候我們其實期望page cleaner 負責清出更多的空閒block。
事實上, webscalesql已經這麼做了。感興趣的可以直接去checkout webscalesql的程式碼看看
http://bugs.mysql.com/bug.php?id=71411
buf_do_LRU_batch函式的返回值表示從LRU上flush的髒頁數,但卻把壓縮表上驅逐的解壓頁也納入了統計。這可能會引起某些innodb_metrics的錯誤值。 這還會影響到page cleaner的刷髒策略。
http://bugs.mysql.com/bug.php?id=74637
讓page cleaner的重新整理策略更加自適應。應該根據redo space 和free list做出自適應的page cleaner策略調整,我(id zhai weixiang) 在bug中也回覆了可行的策略:對於lru_list,percona server有更加聰明的做法,獨立出LRU執行緒並根據free list長度調整sleep時間;對於flush_list,我們可以對sleep的時間做動態調整,根據max_modified_age_sync來進行估算。
可行的改進
針對page cleaner的問題,我基於阿里內部的版本中做了些修改 (感興趣的阿里同學可以找我拿測試branch),大概包含如下幾點:
- 分拆LRU FLUSH到獨立執行緒,根據FREE LIST長度自適應調整刷LRU策略 (from percona)
- PAGE CLEANER支援multi page cleaner (from 5.7)。並根據redo space 計算自適應的刷髒頻率
- 從使用者執行緒移除SINGLE PAGE FLUSH,總是由LRU FLUSH執行緒來釋放空閒page.
- MULTI PAGE CLEANER依然會引起double write buffer的單點競爭。為了解決這個問題,引入多個double write file,每個double write buffer檔案對應特定的buffer pool instance.
相關文章
- MySQL刷髒MySql
- MySQL:刷髒相關MySql
- Java程式的髒資料問題 (轉)Java
- Linux的磁碟快取和刷髒頁Linux快取
- MySQL學習之flush(刷髒頁)MySql
- PostgreSQL的"double buffers"刷髒機制和引數SQL
- Hive 刷題——獎金瓜分問題Hive
- mysql5.7安裝及問題處理MySql
- MySql5.7及以上 ORDER BY 報錯問題MySql
- MySQL5.7原始碼安裝問題彙總MySql原始碼
- 升級到MySQL5.7版本需注意的問題MySql
- 首款刷馬桶機器人上市 髒活累活留給它就好機器人
- Leetcode刷題中關於java的一些小問題LeetCodeJava
- 髒讀!幻讀!不可重複讀!mysql併發事務引發的問題MySql
- 8Manage輕鬆解決採購過程“髒亂差”問題
- vscode刷leetcode無法登入的問題VSCodeLeetCode
- Hive SQL必刷練習題:同時線上人數問題(*****)HiveSQL
- mysql5.7無法開啟二進位制日誌問題MySql
- 刷題學習
- MISC刷題12
- 每日刷題 3.17
- mysql刷題題後感MySql
- LeetCode 刷題指南(一):為什麼要刷題LeetCode
- 中考後刷題補題合集
- 資料庫-刷題資料庫
- 面試刷題總結面試
- 黃綠題選刷
- 刷題筆記02筆記
- 刷題筆記03筆記
- BUU刷題記錄
- 記錄刷題日常
- 我的刷題經驗總結
- Tarjan縮點題單 刷題題解
- 華為機試題刷題總結
- 每天刷個演算法題20160526:BFS解決八數碼問題(九宮格問題)演算法
- 都是髒資料惹的禍
- “骯髒的”IT工作排行榜
- LeetCode刷題:設計問題篇(C++實現,持續更新中...)LeetCodeC++