海山数据库(He3DB)源码详解:海山Mysql 崩溃恢复(3)-日志应用
崩溃恢复之日志应用
recv_recovery_from_checkpoint_start_for_se(flushed_lsn)为崩溃恢复的入口函数,其从innobase_start_or_create_for_mysql()调用,传入参数flushed_lsn是读取存在系统表空间的fil_write_flushed_lsn获得的,该函数在日志解析、日志应用等线程创建之前,进行崩溃恢复操作。
MySQL redo日志崩溃恢复整体流程如图所示,其中,日志应用的流程主要集中在右边部分,recv_parse_or_apply_log_rec_body用于解析或应用日志记录体,recv_recover_page_func用于恢复页面函数,这是应用日志记录到数据库页面的关键步骤。
图中还显示了日志解析和日志应用流程之间的交互,特别是在解析日志记录后,如何将它们应用到数据库页面以完成恢复过程。本文将针对日志应用过程中涉及到的几个函数源码进行详细解析。

1、recv_apply_hashed_log_recs()函数流程
void
recv_apply_hashed_log_recs(
/*=======================*/
ibool allow_ibuf)
{
recv_addr_t* recv_addr;
ulint i;
ibool has_printed = FALSE;
mtr_t mtr;
loop:
mutex_enter(&(recv_sys->mutex));
if (recv_sys->apply_batch_on) {
mutex_exit(&(recv_sys->mutex));
os_thread_sleep(500000);
goto loop;
}
ut_ad(!allow_ibuf == log_mutex_own());
if (!allow_ibuf) {
recv_no_ibuf_operations = true;
}
recv_sys->apply_log_recs = TRUE;
recv_sys->apply_batch_on = TRUE;
for (i = 0; i < hash_get_n_cells(recv_sys->addr_hash); i++) {
for (recv_addr = static_cast<recv_addr_t*>(
HASH_GET_FIRST(recv_sys->addr_hash, i));
recv_addr != 0;
recv_addr = static_cast<recv_addr_t*>(
HASH_GET_NEXT(addr_hash, recv_addr))) {
if (srv_is_tablespace_truncated(recv_addr->space)) {
ut_a(recv_sys->n_addrs);
recv_addr->state = RECV_DISCARDED;
recv_sys->n_addrs--;
continue;
}
if (recv_addr->state == RECV_DISCARDED) {
ut_a(recv_sys->n_addrs);
recv_sys->n_addrs--;
continue;
}
const page_id_t page_id(recv_addr->space,
recv_addr->page_no);
bool found;
const page_size_t& page_size
= fil_space_get_page_size(recv_addr->space,
&found);
ut_ad(found);
if (recv_addr->state == RECV_NOT_PROCESSED) {
if (!has_printed) {
ib::info() << "Starting an apply batch"
" of log records"
" to the database...";
fputs("InnoDB: Progress in percent: ",
stderr);
has_printed = TRUE;
}
mutex_exit(&(recv_sys->mutex));
if (buf_page_peek(page_id)) {
buf_block_t* block;
mtr_start(&mtr);
block = buf_page_get(
page_id, page_size,
RW_X_LATCH, &mtr);
buf_block_dbg_add_level(
block, SYNC_NO_ORDER_CHECK);
recv_recover_page(FALSE, block);
mtr_commit(&mtr);
} else {
recv_read_in_area(page_id);
}
mutex_enter(&(recv_sys->mutex));
}
}
if (has_printed
&& (i * 100) / hash_get_n_cells(recv_sys->addr_hash)
!= ((i + 1) * 100)
/ hash_get_n_cells(recv_sys->addr_hash)) {
fprintf(stderr, "%lu ", (ulong)
((i * 100)
/ hash_get_n_cells(recv_sys->addr_hash)));

最低0.47元/天 解锁文章
1102

被折叠的 条评论
为什么被折叠?



