MySQL核心月報2014.11-MySQL· 5.7改進·Recovery改進

db匠發表於2016-05-23

背景

InnoDB作為事務性引擎,使用write-ahead logging(WAL)機制保證ACID中的Atomicity和Durability,使用undo機制保證ACID中的Consistency和Isolation。

按照WAL和undo的機制,形成以下兩個原則:

1. 資料塊的更改需要先記錄redo日誌。
2. 資料塊的更改需要先寫入undo。

根據這兩個原則,InnoDB更新資料的基本流程可以簡單的總結為:

1. 記錄需要更改undo record的redo log
2. 記錄需要更改data record的redo log
3. 寫入redo log
4. 寫入undo record
5. 更新data record

這5個步驟。


InnoDB Recovery

如果MySQL例項異常crash,那麼重啟過程中首先會進行InnoDB recovery。 即:根據last checkpoint點,順序讀取後面的redo log,按照先前滾,再回滾的原則, 應用所有的redo log。

因為redo record中記錄著資料塊的地址(space_id+page_no),所以recovery的過程首先會執行合併相同資料塊的操作,以加快recovery的過程。


那麼問題來了

根據space_id怎麼找到對應IDB資料檔案?

因為在恢復的過程中,InnoDB只load了redo檔案和系統表空間檔案,如何查詢InnoDB的資料檔案呢?

1. InnoDB的資料字典dict_table_t結構中也儲存了對應關係,但資料字典受redo保護,recovery的過程中不可用。
2. 掃描datadir的所有資料檔案,讀取page中儲存的space_id,建立space_id和資料檔案的對應關係。

MySQL目前採用第二種方式,但帶來了一個問題,當設定了innodb_file_per_table後,每一個表對應一個表空間,那麼需要讀取所有的目錄下的所有Innodb資料檔案,這樣就會嚴重的影響了recovery的時間。


MySQL 5.7改進策略:

MySQL 5.7中,在redo log中增加了一種新的record型別,即MLOG_FILE_NAME,記錄了自last checkpoint以來更改的資料檔案的file name。 這樣在應用的時候,直接根據檔名就可以找到資料檔案。


Oracle的設計機制:

Oracle資料庫recovery的過程中,有沒有這個問題呢? 答案是沒有。

我們來看下Oracle的設計機制:

oracle同樣在系統表空間中記錄了資料字典,受redo保護,可以通過DBA_開頭的表來查詢。但Oracle還維護了一個control file,控制檔案中記錄了database name,redo file,datafile,backup等資訊,通過v$開頭的表查詢。
當Oracle在recovery的過程中,需要資料庫在mount狀態下,即開啟了控制檔案,這時資料字典還不可用(DB沒有open),在應用redo log的時候,根據控制檔案中的v$datafile,檢索file_id和file_name的對應關係。

MySQL是根據datadir,innodb_data_home_dir,innodb_log_group_home_dir等幾個目錄配置,通過檔案系統的查詢,找到相應檔案的,而Oracle維護了一個集中式的control file管理這些初始載入的檔案地址。


相關文章