innodb源碼分析之mini transaction

日誌是innodb一個非常重要的模塊,在innodb中有兩類日誌:redo log和undo log。其中redolog日誌是用來做數據異常恢復和數據庫重啓時頁數據同步恢復的,redo log是建立在在mini transaction基礎上。數據庫在執行事務時,通過minitransaction產生redo log來保證事務的持久性。

1.mini transaction三個協議
        mini-transcation是用來實現innodb的物理邏輯日誌的寫入和頁恢復的,通過mini-transcation來保證併發事務操作和數據庫異常是頁的一致性。爲了得到頁的一致性,mini-transaction遵循以下三個協議:

        1. The FIX Rules

      2. Write-Ahead Log

      3. Force-log-at-commit

1.1The FIX Rules
    The FIX Rules規定如下:

              修改一個頁需要獲得該頁的x-latch

              訪問一個頁是需要獲得該頁的s-latch或者x-latch

              持有該頁的latch直到修改或者訪問該頁的操作完成

1.2Write-Ahead Log
       Write-Ahead Log的意思就是如果一個頁操作在寫入到持久設備時,必須內存中相對應的日誌寫入到持久化設備中。每個頁有一個LSN,每次頁修改需要維護這個LSN,當一個頁需要寫入到持久化設備時,要求內存中小於該頁LSN的日誌先寫入到持久化設備中。日誌寫完後,先Fixed這個頁的latch,再將內存中的頁刷盤。完成刷盤後,釋放頁latch。這裏遵循The FIX Rules協議。

1.3 Force-log-at-commit
       一個事務可以同時修改了多個頁,Write-AheadLog單個數據頁的一致性,無法保證事務的持久性。Force -log-at-commit要求當一個事務提交時,其產生所有的mini-transaction日誌必須刷到持久設備中。這樣即使在頁數據刷盤的時候宕機,也可以通過日誌進行redo恢復。

2 mini-transaction的日誌實現
       innodb是採用mini-transaction來構建操作的物理邏輯日誌的,在事務執行的時候,會通過mtr來保證頁的數據一致性和持久性。mini-transaction是通過一個mtr_t的結構來實現mini-transaction的三個協議。mtr_t的定義如下:

typedef struct mtr_struct
    {
         ulint     state;                      /*mtr的狀態,MTR_ACTIVE、MTR_COMMITING、MTR_COMMITTED*/
         dyn_array_t     memo;        /*正在持有的latch列表*/
         dyn_array_t     log;             /*mtr產生的日誌數據*/
         ibool     modifications;     /*是否修改了頁*/
         ulint     n_log_recs;            /*log操作頁的個數*/
         ulint     log_mode;             /*log操作模式,MTR_LOG_ALL、MTR_LOG_NONE、MTR_LOG_SHORT_INSERTS*/
         dulint     start_lsn;              /*mtr起始的LSN*/
         dulint  end_lsn;             /*mtr結束的LSN*/
         ulint  magic_n;             /*魔法字*/
    }mtr_t;
其中成員memo是個latch持有狀態的數組列表,採用的是dyn_array_t的動態內存結構來保存的,每個單元存儲的是mtr_memo_slot_t這樣的結構。定義如下:
      

typedef struct mtr_memo_slot_struct
        {
             ulint     type;            /*latch的類型值*/
             void*     object;        /*latch對象句柄,可以是rw_lock_t或者buf_block_t*/
        }mtr_memo_slot_t;

latch類型如下:
    MTR_MEMO_PAGE_S_FIX         /*rw_locks-latch*/
    MTR_MEMO_PAGE_X_FIX         /*rw_lockx-latch*/
    MTR_MEMO_BUF_FIX               /*buf_block_t*/
    MTR_MEMO_S_LOCK               /*rw_lock s-latch*/
    MTR_MEMO_X_LOCK               /*rw_lock x-latch*/

 

memo的latch管理接口
    mtr_memo_push                                       獲得一個latch,並將狀態信息存入mtr memo當中
    mtr_release_s_latch_at_savepoint       釋放memo偏移savepoint的slot鎖狀態
    mtr_memo_contains                          判斷鎖對象是否在memo當中
    mtr_memo_slot_release                    釋放slot鎖的控制權
    mtr_memo_pop_all                            釋放所有memo中的鎖的控制權

mt_t中的log成員是也是一個dyn_array_t動態結構的內存,用來保存mtr產生的日誌信息。日誌的寫入是通過mtr0log.h來寫入的。這裏指的一提的是日誌格式,日誌格式是有日誌頭和日誌體組成,日誌頭信息是由type、space和page no組成,由mlog_write_initial_log_record_fast函數寫入到mtr_t的log中的。以下是一個比較具體的示意圖:

      

log body的數據寫入是通過mtr0log.h中的日誌寫入方法進行寫入的。每寫入一跳操作日誌,n_log_recs會加1.

標識modifications是標識是否有page的數據改動,如果有,在mtr_commit調用時會先將mtr->log刷盤,然後釋放mtr所有的所控制權。日誌會一定會在mtr結束時刷盤,這符合Force-log-at-commit的規定。日誌寫入調用的是log_write_low這個函數。

2.1 mtr_t的內存結構關係圖


3 總結
mini transaction是innodb對ACID中的持久性的最小保證單元,所有涉及到事務執行、頁數據刷盤、redo log數據恢復等都需要進行mini transaction的構造和執行。幾乎所有的模塊都涉及到mini transaction,例如:btree、page、事務、inser tbuffer、redo-log等,d對mini transcaion的理解不能孤立的去看源代碼,應該結合redo log、page相關的代碼瞭解。它是理解innodb工作原理的基石。
 

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