對應 worklog:http://dev.mysql.com/worklog/task/?id=7142
對應change log entry:
incompatible change: a new log record type (mlog_file_name) is used to identify file-per-table tablespaces that have been modified since the last checkpoint. this enhancement simplifies tablespace discovery during crash recovery and eliminates scans on the file system prior to redo log application. for more information about the benefits of this enhancement, see tablespace discovery during crash recovery. this enhancement changes the redo log format, requiring that mysql be shut down cleanly before upgrading to or downgrading from mysql 5.7.5.
改進的主要目的是為了消除在crash recovery時對檔案目錄的掃描,因為在innodb層無法根據redo log中的space id直接找到對應的檔案,是以需要打開每個ibd的第一個page來進行判定。
新的修改簡化了上述邏輯,隻有在一次checkpoint後被修改了的表才需要被讀取,其他的幹淨的表空間無需掃描。 在wl#7142中也處理了類似rename這樣的崩潰恢複邏輯,不在本文的讨論範圍之内,後續單獨開文讨論。
mlog_file_create2、mlog_file_create:使用mlog_file_name來代替
mlog_file_rename:使用mlog_file_rename2來代替
增加新類型:
mlog_file_rename2:(space_id, first_page_number, filename, new_filename)
mlog_file_create:(space_id, name)
mlog_checkpoint
詳細見:enum mlog_id_t 枚舉類型中關于各個類型的注釋
當需要修改資料頁時,在開啟一個mini transaction後,需要:
mtr_start(&mtr); mtr.set_named_space(index->space);
set_named_space 會将目前的space id儲存到mtr_t::m_named_space中
mtr_commit時,如果對資料做了修改,那麼在5.7中分為兩步。
入口函數:mtr_t::command::execute
a.mtr_t::command::prepare_write()
#根據set_named_space 函數設定的space id,進行判斷:
fil_space_t* space = is_predefined_tablespace(m_impl->m_named_space) ? null : fil_names_write(m_impl->m_named_space, m_impl->m_mtr);
如果是預定義的系統表空間(ibdata, undo space ,tmp space),space = null; 否則調用函數 fil_names_write(m_impl->m_named_space, m_impl->m_mtr)寫入一個mlog_file_name類型的redo記錄;
#如果該space是上次checkpoint後第一次被修改(調用 fil_names_dirty(space)),需要append一個1位元組的mlog_multi_rec_end類型,因為目前mtr肯定大于1個log 記錄了(一個mtr可能包含多個log rec)
在函數fil_names_dirty中,會判斷space->max_lsn值是否為0,如果為0,表示第一次修改,加入到fil_system->named_spaces連結清單中;否則,設定space->max_lsn為目前的log_sys->lsn; (後面再說何時reset max_lsn為0)
#否則,需要忽略掉在fil_names_write寫入的redo記錄。
b.mtr_t::command::finish_write
将redo log從cache寫入redo log 公共buffer
對應函數log_checkpoint
這裡會調用函數fil_names_clear,周遊fil_system->named_spaces連結清單,如果space->max_lsn的值小于目前做checkpoint的lsn(在該lsn之前的髒頁已經刷盤),則将其中每個space->max_lsn設定為0,并從連結清單取出。同時寫一個mlog_file_name日志(所有named_spaces上的成員)。
然後寫一個mlog_checkpoint日志,參考函數:mtr_t::commit_checkpoint。
是以這個mini transaction應該包含fil_system->named_spaces連結清單上每個成員的mlog_file_name日志以及緊随其後的一個mlog_checkpoint日志
在crash recovery時,會有一個記憶體結構對象來維護space id和表名的映射關系:
typedef std::map< ulint, file_name_t, std::less<ulint>, ut_allocator<std::pair<const ulint, file_name_t> > > recv_spaces_t; static recv_spaces_t recv_spaces;
參考函數:
recv_parse_or_apply_log_rec_body–>fil_name_parse –>fil_name_process
http://bazaar.launchpad.net/~mysql/mysql-server/5.7/revision/7825
http://bazaar.launchpad.net/~mysql/mysql-server/5.7/revision/7829
http://bazaar.launchpad.net/~mysql/mysql-server/5.7/revision/7888
http://bazaar.launchpad.net/~mysql/mysql-server/5.7/revision/7966
http://bazaar.launchpad.net/~mysql/mysql-server/5.7/revision/8152
http://bazaar.launchpad.net/~mysql/mysql-server/5.7/revision/8560