innodb 刷數據

首先innodb 線程分爲用戶態線程和後臺線程,用戶態線程主要是用戶操作的線程,可以通過show process list 查看,後臺線程不能夠查看。但是show innodb status可以查看到4個線程

I/O thread 0 state: waiting for i/o request (insert buffer thread)
I/O thread 1 state: waiting for i/o request (log thread)
I/O thread 2 state: waiting for i/o request (read thread)
I/O thread 3 state: waiting for i/o request (write thread)

IO線程是可以通過innodb_file_io_threads  參數配置,默認是4;

其次innodb 刷數據也分兩種,同步IO及一步IO就是show innodb status 中出現的aio;


在innodb中後臺線程刷數據時異步IO,後臺線程受主線程master_thread調度;master_thread 優先級最高,其內部由幾個循環構成

主 loop ,background loop,flush loop;suspend loop;master thread 運行會在這幾個線程之間切換;


首先說  主loop,主loop 分爲兩類主要操作,每1s和每10s,但是innodb 並不是嚴格按照這個時段來執行的,因爲中間出了切換還有sleep等操作會消耗時間;

在innodb中維護了4個隊列,每個隊列長度256,其中存放的是slot,當隊列滿時,必然會喚醒相關的IO線程執行相應的iO操作,主線程也會週期性的喚醒IO線程;然後檢查自己的隊列,看是否需要做刷盤操作; 這4個線程是異步IO;


每1s喚醒IO線程執行操作

1、日誌緩衝刷新到磁盤,每1s 執行,同時日誌緩衝會受到innodb_flush_log_at_trx_commit  參數配置的影響,但是即使事務沒有提交,也會刷,在刷日誌時,innodb會對時間做一個判斷,首先先看有沒有在隊列裏超過2s的 如果有 就先刷他們,如果沒有超過2s的 也先刷低地址的,然後會遍歷隊列 把幾個在同一個extent的page一起刷下去;

2、合併插入緩衝(可能);innodb會判斷當前IO情況,如果當前1s內少於5次IO,它就認爲當前IO負載較小,執行合併插入;

3、刷新至多100個髒數據頁(可能);如果當前髒頁操過了90%,就是innodb_max_dirty_pages_pct 默認值,那麼它認爲需要刷新髒頁

4、切換到background loop;


每10s喚醒IO線程執行的操作

1、將日誌緩衝刷新到磁盤;

2、合併5個插入緩衝;不管當前IO操作能力如何,總是強制執行;

3、刷新100個髒頁;innodb會判斷過去10s內IO操作是否小於200,如果是,那麼它認爲當前IO比較輕,執行刷新100個髒頁;如果當前髒頁比例大於70%,那麼也會刷新100個髒頁,否則會刷新10個;

4、刪除無用的undo頁;因爲innodb採用了MVCC機制,有些爲了一致性讀而被標記爲刪除狀態數據頁需要被清理,比如有時一個查詢可能需要讀取前一個版本的數據信息,它被放在undo頁中;但是每次最多刪除20個undo頁;

5、產生一個檢查點;innodb 刷數據時會產生一個檢查點;但是沒10s也會強制產生一個檢查點;爲了保證性能,並不是完全刷完髒數據,而是志將最老日誌序列號的頁刷盤;



background loop ,當前沒有或用用戶或者數據庫關閉時就會切換到這個循環;

它會執行以下操作;

1、刪除無用的 undo頁;

2、合併20個插入緩衝;

3、不斷刷新100個數據頁,知道符合條件(可能跳到  flush loop 中完成);


suspend_loop

如果 flush loop中也沒有什麼事情可以做了,innodb 會切換到 suspeng_loop,將master thread掛起,等待事件的發生;如果啓用了innodb 存儲引擎卻沒有innodb表,通用也會將 master thread 掛起;


主線程如下









10         do buffer pool flush 100 dirty page  
11     if ( no user activity )  
12         goto backgroud loop  
13 }  
14 if ( last_ten_second_ios < 200 )  
15     do buffer pool flush 100 dirty page  
16 do merge at most 5 insert buffer  
17 do log buffer flush to disk  
18 do full purge  
19 if ( buf_get_modified_ratio_pct > 70% )  
20     do buffer pool flush 100 dirty page  
21 else  
22     buffer pool flush 10 dirty page  
23 do fuzzy checkpoint  
24 goto loop  
25 background loop:  
26 do full purge  
27 do merge 20 insert buffer  
28 if not idle:  
29 goto loop:  
30 else:  
31     goto flush loop  
32 flush loop:  
33 do buffer pool flush 100 dirty page  
34 if ( buf_get_modified_ratio_pct> innodb_max_dirty_pages_pct )  
35     goto flush loop  
36 goto suspend loop  
37 suspend loop:  
38 suspend_thread()  
39 waiting event  
40 goto loop;  

後續會對innodb plugin 說明


上面說到 的主線程部分大多數是異步IO ,但是用戶態線程大多數是同步IO;

當你發起一個事務時,innodb會判斷log buffer 是否有足夠的空間;如果有那麼就啓動一個事務,如果沒有,那麼就會喚醒log thread 刷日誌,但是並不刷完;同時也會對髒頁做類似處理;


參考 innodb 存儲引擎內幕一書及自己一些學習;






發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章