Master Thread工作方式1

      在上一篇博客InnoDB體系架構 後臺線程中,我們介紹了InnoDB存儲引擎的主要工作都是有Master Thread完成的,在這裏我們具體介紹它的實現和可能存在的問題。我們按照版本的順序來介紹該線程。

1.0.x版本之前:

      Master Thread具有最高的線程優先級別,其內部有多個循環(loop)組成,包括:主循環(loop)、後臺循環(background loop)、刷新循環(flush loop)、暫停循環(suspend loop),Master Thread會根據數據庫的運行狀態在這些循環中切換。

      主循環有兩大部分操作——每秒鐘的操作和每10秒的操作,僞代碼如下:

void master_thread(){
    loop:
    for(int i=0;i<10;i++){
        do thing once per second
        sleep 1 second if necessary        
    }
    do things once per ten seconds
    goto loop:        
}

      可以看到loop循環通過thread sleep來實現,這意味着所謂的每秒一次或者每10,秒一次的操作是不精確的,在負載很大的情況下可能會有延遲,所以我們只能說大概在這個頻率下,此外InnoDB引擎還有其它的方法來儘量保證這個頻率。

      每秒一次的操作包括:日誌緩衝刷新到磁盤,即使這個事務還沒有提交(總是);合併插入緩衝(可能);至多刷新100個InnoDB的緩衝池中的髒頁到磁盤(可能);如果當前用戶沒有活動,切換到後臺循環(可能)。

      每10秒的操作包括:刷新100個髒頁到磁盤(可能的情況下);合併至多5個插入緩衝(總是);將日誌緩衝刷新到磁盤(總是);刪除無用的Undo頁(總是);刷新100個或者10個髒頁到磁盤(總是)。

      在以上的過程中,InnoDB存儲引擎會先判斷過去10秒之內磁盤的IO操作是否小於200次,如果是,InnoDB存儲引擎認爲當前有足夠的磁盤IO操作能力,因此將100個髒頁刷新到磁盤,接着InnoDB存儲引擎會合並插入緩存。不同於每秒一次操作,這次的合併插入緩衝操作總會在這個階段進行。

      接着InnoDB存儲引擎會進行一步full purge操作,即刪除無用的Undo頁,對錶進行update、delete這類操作時,原先的行被標記爲刪除,但是因爲一致性讀的關係還需要保留這些行版本的信息,但是在full purge過程中,InnoDB存儲引擎會判斷當前事務系統中已被刪除的行是否可以被刪除,如果可以就立即將其刪除。InnoDB存儲引擎在執行full purge操作時,每次最多嘗試回收20個undo頁。然後InnoDB存儲引擎會判斷緩衝池中髒頁的比例,若大於70%就刷新100個髒頁到磁盤,否則只刷新10%的髒頁到磁盤。

      接着來看background loop,若當前用戶沒有活動或者數據庫關閉,就會切換到這個循環,background loop會執行以下操作:

刪除無用的Undo頁(總是);合併20個插入緩衝(總是);跳回到主循環(總是);不斷刷新100個頁直到符合條件(可能,跳到flush loop中完成)。

      若flush loop中也沒有什麼事情可以做了,InnoDB存儲引擎會切換到suspend loop,將Master Thread掛起,等待事情的發生。若用戶啓用了InnoDB存儲引擎卻沒有使用任何表,那麼Master Thread總是處於掛起的狀態。

      Master Thread完整的僞代碼如下:

void master_thread(){
        goto loop;
    loop:
    for(int i=0;i<10;i++){
        thread_sleep(1)//sleep 1 second
        do log buffer flush to disk
        if(last_one_second_ios<5)
            do merge at most 5 insert buffer
        if(buf_get_modified_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
        buffer pool flush 10 dirty page
    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;        
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章