MySQL系列:innodb源碼分析之redo log恢複,innodbredo

來源:互聯網
上載者:User

MySQL系列:innodb源碼分析之redo log恢複,innodbredo

在上一篇《innodb源碼分析之重做日誌結構》中我們知道redo log的基本結構和日誌寫入步驟,那麼redo log是怎麼進行資料恢複的呢?在什麼時候進行redo log的日誌推演呢?redo log的推演只有在資料庫異常或者關閉後,資料庫重新啟動時會進行日誌推演,將資料庫狀態恢複到關閉前的狀態。那麼這個過程是怎麼進行的呢?以下我們逐步來解析。

1.recv_sys_t結構 innodb在MySQL啟動的時候,會對重做記錄檔進行日誌重做,重做日誌是通過一個recv_sys_t的結構來進行資料恢複和控制的。它的結構如下:
struct recv_sys_struct{ mutex_t mutex;                                 /*保護鎖*/ ibool apply_log_recs;                        /*正在應用log record到page中*/ ibool apply_batch_on;                     /*批量應用log record標誌*/  dulint lsn; ulint last_log_buf_size; byte* last_block;                             /*恢複時最後的塊記憶體緩衝區*/ byte* last_block_buf_start;             /*最後塊記憶體緩衝區的起始位置,因為last_block是512地址對齊的,需要這個變數記錄free的地址位置*/ byte* buf;                                        /*從日誌塊中讀取的重做日誌資訊資料*/ ulint len; /*buf有效日誌資料長度*/ dulint parse_start_lsn;                       /*開始parse的lsn*/ dulint scanned_lsn;                           /*已經掃描過的lsn序號*/ ulint scanned_checkpoint_no;          /*恢複日誌的checkpoint 序號*/ ulint recovered_offset;                       /*恢複位置的位移量*/ dulint recovered_lsn;                         /*恢複的lsn位置*/ dulint limit_lsn;                                  /*日誌恢複最大的lsn,暫時在日誌重做的過程沒有使用*/ ibool found_corrupt_log;                   /*是否開啟日誌恢複診斷*/ log_group_t*archive_group; mem_heap_t* heap;                             /*recv sys的記憶體配置堆,用來管理恢複過程的記憶體佔用*/ hash_table_t*addr_hash;                     /*recv_addr的hash表,以space id和page no為KEY*/ ulint n_addrs;                                        /*addr_hash中包含recv_addr的個數*/};
在這個結構中,比較複雜的是addr_hash這個雜湊表,這個雜湊表是用sapce_id和page_no作為hash key,裡面儲存有恢複時對應的記錄內容。恢複日誌在從記錄檔中讀出後,進行解析成若干個recv_t並儲存在雜湊表當中。在一個讀取解析周期過後,日誌恢複會對hash表中的recv_t中的資料寫入到ibuf和page中。這裡為什麼要使用hash表呢?個人覺得是為了同一個page的資料批量進行恢複的緣故,這樣可以page減少隨機插入和修改。 以下是和這個過程相關的幾個資料結構:
/*對應頁的資料恢複操作集合*/ struct recv_addr_struct{ ulint state;          /*狀態,RECV_NOT_PROCESSED、RECV_BEING_PROCESSED、RECV_PROCESSED*/ ulint space;         /*space的ID*/ ulint page_no;    /*頁序號*/ UT_LIST_BASE_NODE_T(recv_t) rec_list; hash_node_t addr_hash;};/*當前的記錄操作*/struct recv_struct{ byte type;             /*log類型*/ ulint len;               /*目前記錄資料長度*/ recv_data_t*data; /*當前的記錄資料list*/ dulint start_lsn;     /*mtr起始lsn*/ dulint end_lsn;      /*mtr結尾lns*/ UT_LIST_NODE_T(recv_t)rec_list;};/*具體的資料體*/struct recv_data_struct  { recv_data_t*next;/*下一個recv_data_t,next的地址後面接了一大塊記憶體,用於儲存rec body*/};
他們的記憶體關係結構圖如下:
2.重做日誌推演過程的LSN關係除了這個恢複的雜湊表以外,recv_sys_t中的各種LSN也是和日誌恢複有非常緊密的關係。以下是各種lsn的解釋:    parse_start_lsn    本次日誌重做恢複起始的lsn,如果是從checkpoint處開始恢複,等於checkpoint_lsn。    scanned_lsn        在恢複過程,將恢複日誌從log_sys->buf解析塊後存入recv_sys->buf的日誌lsn.    recovered_lsn      已經將資料恢複到page中或者已經將日誌操作儲存addr_hash當中的日誌lsn;    在日誌開始恢複時:
     parse_start_lsn = scanned_lsn = recovered_lsn = 檢查點的lsn。
   在日誌完成恢複時:
       parse_start_lsn =  檢查點的lsn
       scanned_lsn = recovered_lsn = log_sys->lsn。
在日誌推演過程中lsn大小關係如下:

3.日誌恢複的主要介面和流程恢複日誌主要的介面函數:   recv_recovery_from_checkpoint_start    從重做日誌組內的最近的checkpoint開始恢複資料
    recv_recovery_from_checkpoint_finish  結束從重做日誌組內的checkpoint的資料恢複操作
    recv_recovery_from_archive_start           從歸檔記錄檔中進行資料恢複
    recv_recovery_from_archive_finish         結束從歸檔日誌中的資料恢複操作
    recv_reset_logs                                          截取重做日誌最後一段作為新的重做日誌的起始位置,可能會遺失資料。
重做日誌恢複資料的流程(checkpoint方式)   1.當MySQL啟動的時候,先會從資料庫檔案中讀取出上次儲存最大的LSN。
    2.然後調用recv_recovery_from_checkpoint_start,並將最大的LSN作為參數傳入函數當中。
    3.函數會先最近建立checkpoint的日誌組,並讀取出對應的checkpoint資訊
    4.通過checkpoint lsn和傳入的最大LSN進行比較,如果相等,不進行日誌恢複資料,如果不相等,進行日誌恢複。
    5.在啟動恢複之前,先會同步各個日誌組的archive歸檔狀態
    6.在開始恢複時,先會從記錄檔中讀取2M的日誌資料到log_sys->buf,然後對這2M的資料進行scan,校正其合法性,而後將去掉block header的日誌放入recv_sys->buf當中,這個過程稱為scan,會改變scanned lsn.
    7.在對2M的日誌資料scan後,innodb會對日誌進行mtr操作解析,並執行相關的mtr函數。如果mtr合法,會將對應的記錄資料按space page_no作為KEY存入recv_sys->addr_hash當中。
    8.當對scan的日誌資料進行mtr解析後,innodb對會調用recv_apply_hashed_log_recs對整個recv_sys->addr_hash進行掃描,並按照日誌相對應的操作進行對應page的資料恢複。這個過程會改變recovered_lsn。
    9.如果完成第8步後,會再次從日誌組檔案中讀取2M資料,跳到步驟6繼續相對應的處理,直到記錄檔沒有需要恢複的日誌資料。
    10.innodb在恢複完成記錄檔中的資料後,會調用recv_recovery_from_checkpoint_finish結束日誌恢複操作,主要是釋放一些開闢的記憶體。並進行事務和binlog的處理。
上面過程的如下:



相關文章

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.