一、Master Thead簡單介紹
innoDB存儲引擎的主要工作都是由Master Thread 完成的。master thread的線程優先級別最高。其內部幾個循環(loop)組成:主循環(loop),後臺循環(background loop),刷新循環(flush loop),暫停循環(suspend loop).master thread會根據數據運行的狀態在loop,background
loop,flush loop和suspend loop中進行切換.
loop稱爲主循環,因爲大多數的操作都在這個循環中,其中有兩大部分操作:每秒鐘的操作和每10秒的操作。
二、兩種操作
1、每秒一次的操作包括:
1)日誌緩衝刷新到磁盤,即使這個事務還沒有提交(總是)
2)合併插入緩衝(可能)
3)至多刷新100個innodb的緩衝池中的髒頁到磁盤(可能)
4)如果當前沒有用戶活動,切換到background loop(可能)
即使某個事務還沒有提交,innodb存儲引擎仍然會每秒將重做日誌緩衝中的內容刷新到重做日誌文件.這一點是必須知道的,這可以很好地解釋爲什麼再大的事務commit的時間也是很快的
合併插入緩衝(insert buffer)並不是每秒都發生.innodb存儲引擎會判斷當前一秒內發生的io次數是否小於5次,如果小於5次,innodb認爲當前的io壓力很小,可以執行合併插入緩衝的操作
同樣,刷新100個髒頁也不是每秒都在發生.innodb存儲引擎通過判斷當前緩衝池中的髒頁比例(buf_get_modified_ratio_pct)是否超過了配置文件中innodb_max_dirty_pages_pct這個參數(默認爲90,代表90%),如果超過了這個闕值,innodb存儲引擎認爲需要做磁盤同步操作,將100個髒頁寫入磁盤.
2、每10秒的操作
1)刷新100個髒頁到磁盤(可能)
2)合併至多5個插入緩衝(總是)
3)將日誌緩衝刷新到磁盤(總是)
4)刪除無用的undo頁(總是)
5)刷新100個或者10個髒頁到磁盤(總是)
6)產生一個檢查點(總是)
在以上過程中,innodb存儲引擎會先判斷過去10秒之內的磁盤的io操作是否小於200次.如果是,innodb存儲引擎認爲當前有足夠的磁盤io能力,因此將100個髒頁刷新到磁盤.接着,innodb存儲引擎會合並插入緩衝.不同於1秒操作時可能發生的合併插入緩衝操作,這次的合併插入緩衝操作總會在這個階段進行.之後,innodb存儲引擎會再執行一次將日誌緩衝刷新到磁盤的操作,這與每秒發生的操作是一樣的.
接着innodb存儲引擎會執行一步full purge操作,即刪除無用的undo頁.對錶執行update,delete這類操作時,原生的行被標記爲刪除,但是因爲一致性讀的關係,需要保留這些行版本的信息.但是在full purge過程中,innodb存儲引擎會判斷當前事務系統中已被刪除的行是否可以刪除,比如有時候可能還有查詢操作需要讀取之前版本的undo信息,如果可以,innodb會立即將其刪除.從源代碼中可以發現,innodb存儲引擎在操作full
purge時,每次最多刪除20個undo頁.
然後innodb存儲引擎會判斷緩衝池中髒頁的比例,如果有超過70%的髒頁,則刷新100個髒頁到磁盤;如果髒頁得比例小於70%,則只需要刷新10的髒頁到磁盤
最後,innodb存儲引擎會產生一個檢查點(checkpoint),innodb存儲引擎的檢查點也被稱爲模糊檢查點(fuzzy checkpoint).innodb存儲引擎在checkpoint時並不會把所有緩衝池中的髒頁都寫到磁盤,因爲這樣可能會對性能產生影響,而只是將最老日誌序列號的頁寫入磁盤。
接着來看background
loop,若當前沒有用戶活動(數據庫空閒時)或者數據庫關閉時,就會切換到這個循環.這個循環會執行如下操作:
刪除無用的undo頁(總是).
合併20個插入緩衝(總是).
跳回到主循環(總是).
不斷刷新100個頁,直到符合條件(可能,跳轉到flush loop中完成)
如果flush loop中也沒有什麼事情可以做了,innodb存儲引擎會切換到supend_loop,將master thread掛起,等待事件的發生.若啓用了innodb存儲引擎,卻沒有使用任何存儲引擎的表,那麼master thread總是處於掛起狀態.
三、僞代碼
接着來看background
loop,若當前沒有用戶活動(數據庫空閒時)或者數據庫關閉時,就會切換到這個循環.這個循環會執行如下操作:
刪除無用的undo頁(總是).
合併20個插入緩衝(總是).
跳回到主循環(總是).
不斷刷新100個頁,直到符合條件(可能,跳轉到flush loop中完成)
如果flush loop中也沒有什麼事情可以做了,innodb存儲引擎會切換到supend_loop,將master thread掛起,等待事件的發生.若啓用了innodb存儲引擎,卻沒有使用任何存儲引擎的表,那麼master thread總是處於掛起狀態.
- void master_thread(){
- goto loop;
- loop:
- for(int i=0;i<10;i++){
- thread_sleep(1);
- do log buffer flush to disk
- if(last_one_second_ios < 5)
- do merge at most 5 insert buffer
- if(buf_get_modifed_ratio_pct > innodb_max_dirty_pages_pct)
- do buffer pool flush 100 dirty page
- if(no user activity)
- goto background loop
- }
- if(last_ten_second_ios<200)
- do buffer pool flush 100 dirty page
- do merge at most 5 insert buffer
- do log buffer flush to disk
- do full purge
- if(buf_get_modified_ratio_pct > 70%)
- do buffer pool flush 100 dirty page
- else
- do buffer pool flush 10 dirty page
- do fuzzy checkpoint
- goto loop
- background loop:
- do full purge
- do merge 20 insert buffer
- if not idle:
- goto loop:
- else:
- goto flush loop
- flush loop:
- do buffer pool flush 100 dirty page
- if(buf_get_modified_ratio_pct > innodb_max_dirty_pages_pct)
- goto flush loop
- goto suspend loop
- suspend loop:
- suspend_thread();
- waiting event
- goto loop;
- }