MySQL Innodb日誌機制深入分析

2011-06-25 21:45 2255人閱讀 評論(0) 收藏 舉報

目錄(?)[+]

                            MySQL Innodb日誌機制深入分析

 

1.1. Log & Checkpoint

Innodb的事務日誌是指Redo log,簡稱Log,保存在日誌文件ib_logfile*裏面。Innodb還有另外一個日誌Undo log,但Undo log是存放在共享表空間裏面的(ibdata*文件)。

 

由於Log和Checkpoint緊密相關,因此將這兩部分合在一起分析。

名詞解釋:LSN,日誌序列號,Innodb的日誌序列號是一個64位的整型。

 

1.1.1. 寫入機制

1.1.1.1. Log寫入

 

LSN實際上對應日誌文件的偏移量,新的LSN=舊的LSN + 寫入的日誌大小。舉例如下:

LSN=1G,日誌文件大小總共爲600M,本次寫入512字節,則實際寫入操作爲:

l 求出偏移量:由於LSN數值遠大於日誌文件大小,因此通過取餘方式,得到偏移量爲400M;

l 寫入日誌:找到偏移400M的位置,寫入512字節日誌內容,下一個事務的LSN就是1000000512;

 

1.1.1.2. Checkpoint寫入

 

Innodb實現了Fuzzy Checkpoint的機制,每次取到最老的髒頁,然後確保此髒頁對應的LSN之前的LSN都已經寫入日誌文件,再將此髒頁的LSN作爲Checkpoint點記錄到日誌文件,意思就是“此LSN之前的LSN對應的日誌和數據都已經寫入磁盤文件”。恢復數據文件的時候,Innodb掃描日誌文件,當發現LSN小於Checkpoint對應的LSN,就認爲恢復已經完成。

Checkpoint寫入的位置在日誌文件開頭固定的偏移量處,即每次寫Checkpoint都覆蓋之前的Checkpoint信息。

 

 

1.1.2. 管理機制

 

由於Checkpoint和日誌緊密相關,將日誌和Checkpoint一起說明,詳細的實現機制如下:

 

 

如上圖所示,Innodb的一條事務日誌共經歷4個階段:

l 創建階段:事務創建一條日誌;

l 日誌刷盤:日誌寫入到磁盤上的日誌文件;

l 數據刷盤:日誌對應的髒頁數據寫入到磁盤上的數據文件;

l 寫CKP:日誌被當作Checkpoint寫入日誌文件;

 

 

對應這4個階段,系統記錄了4個日誌相關的信息,用於其它各種處理使用:

l Log sequence number(LSN1):當前系統LSN最大值,新的事務日誌LSN將在此基礎上生成(LSN1+新日誌的大小);

l Log flushed up to(LSN2):當前已經寫入日誌文件的LSN;

l Oldest modified data log(LSN3):當前最舊的髒頁數據對應的LSN,寫Checkpoint的時候直接將此LSN寫入到日誌文件;

l Last checkpoint at(LSN4):當前已經寫入Checkpoint的LSN;

 

 

對於系統來說,以上4個LSN是遞減的,即: LSN1>=LSN2>=LSN3>=LSN4.

 

具體的樣例如下(使用show innodb status /G命令查看,Oldest modified data log沒有顯示):

 

 

 

1.1.3. 保護機制

 

Innodb的數據並不是實時寫盤的,爲了避免宕機時數據丟失,保證數據的ACID屬性,Innodb至少要保證數據對應的日誌不能丟失。對於不同的情況,Innodb採取不同的對策:

l 宕機導致日誌丟失
Innodb有日誌刷盤機制,可以通過innodb_flush_log_at_trx_commit參數進行控制;

l 日誌覆蓋導致日誌丟失

Innodb日誌文件大小是固定的,寫入的時候通過取餘來計算偏移量,這樣存在兩個LSN寫入到同一位置的可能,後面寫的把前面寫得就覆蓋了,以“寫入機制”章節的樣例爲例,LSN=100000000和LSN=1600000000兩個日誌的偏移量是相同的了。這種情況下,爲了保證數據一致性,必須要求LSN=1000000000對應的髒頁數據都已經刷到磁盤中,也就是要求Last checkpoint對應的LSN一定要大於1000000000,否則覆蓋後日志也沒有了,數據也沒有刷盤,一旦宕機,數據就丟失了。

 

 

爲了解決第二種情況導致數據丟失的問題,Innodb實現了一套日誌保護機制,詳細實現如下:

 

 

上圖中,直線代表日誌空間(Log cap,約等於日誌文件總大小*0.8,0.8是一個安全係數),Ckp age和Buf age是兩個浮動的點,Buf async、Buf sync、Ckp async、Ckp sync是幾個固定的點。各個概念的含義如下:

概念

計算

含義

Ckp age

LSN1- LSN4

還沒有做Checkpoint的日誌範圍,若Ckp age超過日誌空間,說明被覆蓋的日誌(LSN1-LSN4-Log cap)對應日誌和數據“可能”還沒有刷到磁盤上

Buf age

LSN1- LSN3

還沒有將髒頁刷盤的日誌的範圍,若Buf age超過日誌空間,說明被覆蓋的日誌(LSN1-LSN3-Log cap)對應數據“肯定”還沒有刷到磁盤上

Buf async

日誌空間大小 * 7/8

強制將Buf age-Buf async的髒頁刷盤,此時事務還可以繼續執行,所以爲async,對事務的執行速度沒有直接影響(有間接影響,例如CPU和磁盤更忙了,事務的執行速度可能受到影響)

Buf sync

日誌空間大小 * 15/16

強制將2*(Buf age-Buf async)的髒頁刷盤,此時事務停止執行,所以爲sync,由於有大量的髒頁刷盤,因此阻塞的時間比Ckp sync要長。

Ckp async

日誌空間大小 * 31/32

強制寫Checkpoint,此時事務還可以繼續執行,所以爲async,對事務的執行速度沒有影響(間接影響也不大,因爲寫Checkpoint的操作比較簡單)

Ckp sync

日誌空間大小 * 64/64

強制寫Checkpoint,此時事務停止執行,所以爲sync,但由於寫Checkpoint的操作比較簡單,即使阻塞,時間也很短

 

當事務執行速度大於髒頁刷盤速度時,Ckp age和Buf age會逐步增長,當達到async點的時候,強制進行髒頁刷盤或者寫Checkpoint,如果這樣做還是趕不上事務執行的速度,則爲了避免數據丟失,到達sync點的時候,會阻塞其它所有的事務,專門進行髒頁刷盤或者寫Checkpoint。

 

因此從理論上來說,只要事務執行速度大於髒頁刷盤速度,最終都會觸發日誌保護機制,進而將事務阻塞,導致MySQL操作掛起。

 

 

由於寫Checkpoint本身的操作相比寫髒頁要簡單,耗費時間也要少得多,且Ckp sync點在Buf sync點之後,因此絕大部分的阻塞都是阻塞在了Buf sync點,這也是當事務阻塞的時候,IO很高的原因,因爲這個時候在不斷的刷髒頁數據到磁盤。例如如下截圖的日誌顯示了很多事務阻塞在了Buf sync點:

 

附註:Innodb的日誌保護機制實現可以參考log0log.c文件的void log_check_margins(void)函數。

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