diff --git a/storage/innobase/include/log0log.h b/storage/innobase/include/log0log.h index 08846a5..040efdd 100644 --- a/storage/innobase/include/log0log.h +++ b/storage/innobase/include/log0log.h @@ -525,6 +525,7 @@ extern my_bool innodb_log_checksums; #define LOG_CHECKPOINT_LSN 8 #define LOG_CHECKPOINT_OFFSET 16 #define LOG_CHECKPOINT_LOG_BUF_SIZE 24 +#define LOG_M_CHECKPOINT_LSN 32 /** Offsets of a log file header */ /* @{ */ @@ -726,6 +727,8 @@ struct log_t{ /*!< latest checkpoint lsn */ lsn_t next_checkpoint_lsn; /*!< next checkpoint lsn */ + lsn_t next_m_checkpoint; /*!< where m_checkpoint stored while making + next checkpoint. */ mtr_buf_t* append_on_checkpoint; /*!< extra redo log records to write during a checkpoint, or NULL if none. diff --git a/storage/innobase/log/log0log.cc b/storage/innobase/log/log0log.cc index 3a01cdf..4fb0a54 100644 --- a/storage/innobase/log/log0log.cc +++ b/storage/innobase/log/log0log.cc @@ -823,6 +823,8 @@ log_init(void) log_sys->last_checkpoint_lsn = log_sys->lsn; + log_sys->next_m_checkpoint = 0; + rw_lock_create( checkpoint_lock_key, &log_sys->checkpoint_lock, SYNC_NO_ORDER_CHECK); @@ -1595,6 +1597,7 @@ log_group_checkpoint( group); mach_write_to_8(buf + LOG_CHECKPOINT_OFFSET, lsn_offset); mach_write_to_8(buf + LOG_CHECKPOINT_LOG_BUF_SIZE, log_sys->buf_size); + mach_write_to_8(buf + LOG_M_CHECKPOINT_LSN, log_sys->next_m_checkpoint); log_block_set_checksum(buf, log_block_calc_checksum_crc32(buf)); @@ -1756,6 +1759,7 @@ log_checkpoint( bool write_always) { lsn_t oldest_lsn; + lsn_t m_checkpoint_start = 0; ut_ad(!srv_read_only_mode); @@ -1816,6 +1820,10 @@ log_checkpoint( = srv_shutdown_state == SRV_SHUTDOWN_NONE || flush_lsn != log_sys->lsn; + if (do_write) { + m_checkpoint_start = log_sys->lsn; + } + if (fil_names_clear(flush_lsn, do_write)) { ut_ad(log_sys->lsn >= flush_lsn + SIZE_OF_MLOG_CHECKPOINT); flush_lsn = log_sys->lsn; @@ -1862,6 +1870,7 @@ log_checkpoint( return(false); } + log_sys->next_m_checkpoint = m_checkpoint_start; log_sys->next_checkpoint_lsn = oldest_lsn; log_write_checkpoint_info(sync); ut_ad(!log_mutex_own()); diff --git a/storage/innobase/log/log0recv.cc b/storage/innobase/log/log0recv.cc index 93d8f55..ad41e5f 100644 --- a/storage/innobase/log/log0recv.cc +++ b/storage/innobase/log/log0recv.cc @@ -3780,6 +3780,7 @@ Parses and hashes the log records if new data found. @param[in,out] group log group @param[in,out] contiguous_lsn log sequence number until which all redo log has been scanned +@param[in] checkpoint_lsn lsn where checkpoint has been made @param[in] last_phase whether changes can be applied to the tablespaces @return whether rescan is needed (not everything was stored) */ @@ -3788,6 +3789,7 @@ bool recv_group_scan_log_recs( log_group_t* group, lsn_t* contiguous_lsn, + lsn_t checkpoint_lsn, bool last_phase) { DBUG_ENTER("recv_group_scan_log_recs"); @@ -3810,7 +3812,6 @@ recv_group_scan_log_recs( ut_ad(last_phase || !recv_writer_thread_active); mutex_exit(&recv_sys->mutex); - lsn_t checkpoint_lsn = *contiguous_lsn; lsn_t start_lsn; lsn_t end_lsn; store_t store_to_hash = recv_sys->mlog_checkpoint_lsn == 0 @@ -4019,6 +4020,7 @@ recv_recovery_from_checkpoint_start( byte* buf; byte log_hdr_buf[LOG_FILE_HDR_SIZE]; dberr_t err; + lsn_t stored_checkpoint_lsn = 0; /* Initialize red-black tree for fast insertions into the flush_list during recovery process. */ @@ -4053,6 +4055,7 @@ recv_recovery_from_checkpoint_start( checkpoint_lsn = mach_read_from_8(buf + LOG_CHECKPOINT_LSN); checkpoint_no = mach_read_from_8(buf + LOG_CHECKPOINT_NO); + stored_checkpoint_lsn = mach_read_from_8(buf + LOG_M_CHECKPOINT_LSN); /* Read the first log file header to print a note if this is a recovery from a restored InnoDB Hot Backup */ @@ -4123,8 +4126,16 @@ recv_recovery_from_checkpoint_start( return(DB_ERROR); } + if (stored_checkpoint_lsn > checkpoint_lsn) { + ib::info() << "checkpoint_lsn is " << checkpoint_lsn + << " and jump to " << stored_checkpoint_lsn + << " to search for MLOG_CHECKPOINT"; + + contiguous_lsn = stored_checkpoint_lsn; + } + /* Look for MLOG_CHECKPOINT. */ - recv_group_scan_log_recs(group, &contiguous_lsn, false); + recv_group_scan_log_recs(group, &contiguous_lsn, checkpoint_lsn, false); /* The first scan should not have stored or applied any records. */ ut_ad(recv_sys->n_addrs == 0); ut_ad(!recv_sys->found_corrupt_fs); @@ -4152,7 +4163,7 @@ recv_recovery_from_checkpoint_start( } else { contiguous_lsn = checkpoint_lsn; rescan = recv_group_scan_log_recs( - group, &contiguous_lsn, false); + group, &contiguous_lsn, checkpoint_lsn, false); if ((recv_sys->found_corrupt_log && !srv_force_recovery) || recv_sys->found_corrupt_fs) { @@ -4206,7 +4217,7 @@ recv_recovery_from_checkpoint_start( if (rescan) { contiguous_lsn = checkpoint_lsn; - recv_group_scan_log_recs(group, &contiguous_lsn, true); + recv_group_scan_log_recs(group, &contiguous_lsn, checkpoint_lsn, true); if ((recv_sys->found_corrupt_log && !srv_force_recovery)