MySQL 5.7 :新的日志类型MLOG_FILE_NAME来避免崩溃恢复时扫描全部ibd

前言

对应 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这样的崩溃恢复逻辑,不在本文的讨论范围之内,后续单独开文讨论。

 

更改:

1.REDO LOG类型修改

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 枚举类型中关于各个类型的注释

 

2.Mini Transaction事务提交时的修改

 

当需要修改数据页时,在开启一个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

 

3. Redo checkpoint

对应函数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日志

 

4.崩溃恢复

 

在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

 

原创文章,转载请注明: 转载自Simple Life

本文链接地址: MySQL 5.7 :新的日志类型MLOG_FILE_NAME来避免崩溃恢复时扫描全部ibd

Post Footer automatically generated by wp-posturl plugin for wordpress.


Comments

Leave a Reply

Your email address will not be published. Name and email are required


Current month ye@r day *