InnoDB存儲引擎後臺線程中的master thread

InnoDB存儲引擎的主要工作都是在一個單獨的後臺線程master thread中完成的。
master thread主線程中主要包括以下幾個循環:
主循環 loop
後臺循環background loop
刷新循環flush loop
暫停循環suspend loop

void master_thread() {
loop:
	for (int i = 0; i < 10; i++)
	{
		sleep 1 second if necessary
		do things once per second // 1、每秒1次的操作
		if (no user activity) // 如果當前沒有用戶活動,切換到後臺循環
			goto background loop;
	}
	do things once per ten seconds // 2、每10秒一次的操作
	goto loop;
background loop:
	do something // 3、數據庫空閒時或數據庫關閉時的操作
	if (not idle) // 非空閒切換到主循環
		goto loop;
	else // 空閒時切換到刷新循環
		goto flush loop;
flush loop:
	do buffer pool flush 100 dirty page // 刷新100個髒頁到磁盤
	// 緩存池中髒頁的比例>某個閾值,默認爲90%,不斷刷新100個髒頁到磁盤
	if (buf_get_modified_ratio_pct > innodb_max_dirty_pages_pct)
		goto flush loop;
	goto suspend loop; // 切換到暫停循環,將master thread掛起
suspend loop:
	suspend_thread()
	waiting event
	goto loop;
}
1、每秒1次的操作
(1)重做日誌緩衝刷新到磁盤,即使這個事務還沒有提交(這可以解釋爲什麼再大的事務commit的時間也是很快的);
(2)判斷當前1秒內IO是否<5次,是則說明當前IO壓力很小,可合併插入緩衝;
(3)判斷當前緩衝池中的髒頁比例buf_get_modified_ratio_pct是否>innodb_max_dirty_pages_pct,超過這個閾值說明需要做磁盤同步操作,將100個髒頁寫入磁盤;
(4)如果當前沒有用戶活動,切換到background loop後臺循環中。
2、每10秒一次的操作
(1)判斷過去10秒之內IO是否<200,是則認爲當前有足夠的磁盤IO能力,將刷新100個髒頁到磁盤;
(2)合併至多5個插入緩衝;
(3)將日誌緩衝刷新到磁盤;
(4)執行一次full purge操作,刪除無用的undo頁(每次最多刪除20個)->作用:對錶執行update、delete這類操作,原先的行會被標記爲刪除,但是爲了一致性讀,需要保留這些行版本的信息。但是在full purge操作時,會判斷當前事務系統中已被刪除的行是否可以被刪除(比如有時候可能還有查詢操作需要讀取之前版本的undo信息),如果可以,InnoDB會立即將其刪除。
(5)刷新100個或10個髒頁到磁盤(髒頁比例>70%,則刷新100個;<70%,則刷新10個);
(6)產生一個checkpoint檢查點,爲fuzzy checkpoint模糊檢查點。InnoDB存儲引擎在checkpoint時並不會把所有緩衝池中的髒頁都寫入到磁盤,因爲這樣可能會對性能產生影響,而只是將oldest LSN最老日誌序列號的頁寫入磁盤。
3、數據庫空閒時或數據庫關閉時的操作
(1)刪除無用的undo頁;
(2)合併20個插入緩衝;
(3)跳回到主循環;
(4)不斷刷新100個髒頁到磁盤,直到符合條件(可能跳轉到flush loop中完成)。


master thread中潛在的問題:硬編碼hard coding
(1)最多隻會刷新100個髒頁,合併5個插入緩衝;
問題:當密集寫時,“忙不過來”,很慢;且發生宕機需要恢復時,由於很多數據還沒有刷新到磁盤,可能會導致恢復需要很長的時間。
修正:參照google patch,提供磁盤IO吞吐量參數innodb_io_capacity,默認200,刷新100%髒頁、合併5%插入緩衝。
(2)髒頁比例innodb_max_dirty_pages_pct默認爲90%
問題:該值“太大了”,如果有很大的內存或者數據庫服務器的壓力很大時,刷新髒頁的速度反而可能會降低;同時,在數據庫恢復階段可能需要更多的時間。

修正:innodb_max_dirty_pages_pct默認90%->默認75%,且通過innodb_adaptive_flushing自適應地刷新影響每一秒刷新髒頁的數量(通過一個buf_flush_get_desired_flush_rate函數判斷需要刷新髒頁最合適的數量,buf_flush_get_desired_flush_rate函數通過判斷產生重做日誌的速度來判斷最合適的刷新髒頁的數量)。

參考:<MySQL技術內幕 InnoDB存儲引擎>

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