diff options
Diffstat (limited to 'storage/innobase/log/log0recv.cc')
-rw-r--r-- | storage/innobase/log/log0recv.cc | 408 |
1 files changed, 169 insertions, 239 deletions
diff --git a/storage/innobase/log/log0recv.cc b/storage/innobase/log/log0recv.cc index c0521f1dba4..68c3e5ccc2c 100644 --- a/storage/innobase/log/log0recv.cc +++ b/storage/innobase/log/log0recv.cc @@ -60,7 +60,7 @@ Created 9/20/1997 Heikki Tuuri #include "row0merge.h" /** Log records are stored in the hash table in chunks at most of this size; -this must be less than UNIV_PAGE_SIZE as it is stored in the buffer pool */ +this must be less than srv_page_size as it is stored in the buffer pool */ #define RECV_DATA_BLOCK_SIZE (MEM_MAX_ALLOC_IN_BUF - sizeof(recv_data_t)) /** Read-ahead area in applying log records to file pages */ @@ -77,7 +77,7 @@ volatile bool recv_recovery_on; bool recv_needed_recovery; #ifdef UNIV_DEBUG /** TRUE if writing to the redo log (mtr_commit) is forbidden. -Protected by log_sys->mutex. */ +Protected by log_sys.mutex. */ bool recv_no_log_write = false; #endif /* UNIV_DEBUG */ @@ -734,7 +734,9 @@ recv_sys_close() os_event_destroy(recv_sys->flush_end); } - ut_free(recv_sys->buf); + if (recv_sys->buf != NULL) { + ut_free_dodump(recv_sys->buf, recv_sys->buf_size); + } ut_ad(!recv_writer_thread_active); mutex_free(&recv_sys->writer_mutex); @@ -794,7 +796,7 @@ DECLARE_THREAD(recv_writer_thread)( /* Wait till we get a signal to clean the LRU list. Bounded by max wait time of 100ms. */ - ib_uint64_t sig_count = os_event_reset(buf_flush_event); + int64_t sig_count = os_event_reset(buf_flush_event); os_event_wait_time_low(buf_flush_event, 100000, sig_count); mutex_enter(&recv_sys->writer_mutex); @@ -850,7 +852,8 @@ recv_sys_init() } recv_sys->buf = static_cast<byte*>( - ut_malloc_nokey(RECV_PARSING_BUF_SIZE)); + ut_malloc_dontdump(RECV_PARSING_BUF_SIZE)); + recv_sys->buf_size = RECV_PARSING_BUF_SIZE; recv_sys->addr_hash = hash_create(size / 512); recv_sys->progress_time = ut_time(); @@ -884,8 +887,9 @@ recv_sys_debug_free(void) hash_table_free(recv_sys->addr_hash); mem_heap_free(recv_sys->heap); - ut_free(recv_sys->buf); + ut_free_dodump(recv_sys->buf, recv_sys->buf_size); + recv_sys->buf_size = 0; recv_sys->buf = NULL; recv_sys->heap = NULL; recv_sys->addr_hash = NULL; @@ -901,57 +905,46 @@ recv_sys_debug_free(void) mutex_exit(&(recv_sys->mutex)); } -/** Read a log segment to a buffer. -@param[out] buf buffer -@param[in] group redo log files -@param[in, out] start_lsn in : read area start, out: the last read valid lsn +/** Read a log segment to log_sys.buf. +@param[in,out] start_lsn in: read area start, +out: the last read valid lsn @param[in] end_lsn read area end -@param[out] invalid_block - invalid, (maybe incompletely written) block encountered -@return false, if invalid block encountered (e.g checksum mismatch), true otherwise */ -bool -log_group_read_log_seg( - byte* buf, - const log_group_t* group, - lsn_t *start_lsn, - lsn_t end_lsn) +@return whether no invalid blocks (e.g checksum mismatch) were found */ +bool log_t::files::read_log_seg(lsn_t* start_lsn, lsn_t end_lsn) { ulint len; - lsn_t source_offset; bool success = true; - ut_ad(log_mutex_own()); + ut_ad(log_sys.mutex.is_owned()); ut_ad(!(*start_lsn % OS_FILE_LOG_BLOCK_SIZE)); ut_ad(!(end_lsn % OS_FILE_LOG_BLOCK_SIZE)); - + byte* buf = log_sys.buf; loop: - source_offset = log_group_calc_lsn_offset(*start_lsn, group); + lsn_t source_offset = calc_lsn_offset(*start_lsn); ut_a(end_lsn - *start_lsn <= ULINT_MAX); len = (ulint) (end_lsn - *start_lsn); ut_ad(len != 0); - const bool at_eof = (source_offset % group->file_size) + len - > group->file_size; + const bool at_eof = (source_offset % file_size) + len > file_size; if (at_eof) { /* If the above condition is true then len (which is ulint) is > the expression below, so the typecast is ok */ - len = (ulint) (group->file_size - - (source_offset % group->file_size)); + len = ulint(file_size - (source_offset % file_size)); } - log_sys->n_log_ios++; + log_sys.n_log_ios++; MONITOR_INC(MONITOR_LOG_IO); - ut_a(source_offset / UNIV_PAGE_SIZE <= ULINT_MAX); + ut_a((source_offset >> srv_page_size_shift) <= ULINT_MAX); - const ulint page_no - = (ulint) (source_offset / univ_page_size.physical()); + const ulint page_no = ulint(source_offset >> srv_page_size_shift); fil_io(IORequestLogRead, true, page_id_t(SRV_LOG_SPACE_FIRST_ID, page_no), univ_page_size, - (ulint) (source_offset % univ_page_size.physical()), + ulint(source_offset & (srv_page_size - 1)), len, buf, NULL); for (ulint l = 0; l < len; l += OS_FILE_LOG_BLOCK_SIZE, @@ -971,7 +964,7 @@ fail: break; } - if (innodb_log_checksums || group->is_encrypted()) { + if (innodb_log_checksums || is_encrypted()) { ulint crc = log_block_calc_checksum_crc32(buf); ulint cksum = log_block_get_checksum(buf); @@ -992,7 +985,7 @@ fail: goto fail; } - if (group->is_encrypted()) { + if (is_encrypted()) { log_crypt(buf, *start_lsn, OS_FILE_LOG_BLOCK_SIZE, true); } @@ -1038,14 +1031,10 @@ recv_synchronize_groups() the block is always incomplete */ lsn_t start_lsn = ut_uint64_align_down(recovered_lsn, - OS_FILE_LOG_BLOCK_SIZE); - log_group_read_log_seg(log_sys->buf, &log_sys->log, - &start_lsn, start_lsn + OS_FILE_LOG_BLOCK_SIZE); - - /* Update the fields in the group struct to correspond to - recovered_lsn */ - - log_group_set_fields(&log_sys->log, recovered_lsn); + OS_FILE_LOG_BLOCK_SIZE); + log_sys.log.read_log_seg(&start_lsn, + start_lsn + OS_FILE_LOG_BLOCK_SIZE); + log_sys.log.set_fields(recovered_lsn); /* Copy the checkpoint info to the log; remember that we have incremented checkpoint_no by one, and the info will not be written @@ -1071,19 +1060,17 @@ recv_check_log_header_checksum( } /** Find the latest checkpoint in the format-0 log header. -@param[out] max_group log group, or NULL @param[out] max_field LOG_CHECKPOINT_1 or LOG_CHECKPOINT_2 @return error code or DB_SUCCESS */ static MY_ATTRIBUTE((warn_unused_result)) dberr_t -recv_find_max_checkpoint_0(log_group_t** max_group, ulint* max_field) +recv_find_max_checkpoint_0(ulint* max_field) { - log_group_t* group = &log_sys->log; ib_uint64_t max_no = 0; ib_uint64_t checkpoint_no; - byte* buf = log_sys->checkpoint_buf; + byte* buf = log_sys.checkpoint_buf; - ut_ad(group->format == 0); + ut_ad(log_sys.log.format == 0); /** Offset of the first checkpoint checksum */ static const uint CHECKSUM_1 = 288; @@ -1094,11 +1081,11 @@ recv_find_max_checkpoint_0(log_group_t** max_group, ulint* max_field) /** Least significant bits of the checkpoint offset */ static const uint OFFSET_LOW32 = 16; - *max_group = NULL; + bool found = false; for (ulint field = LOG_CHECKPOINT_1; field <= LOG_CHECKPOINT_2; field += LOG_CHECKPOINT_2 - LOG_CHECKPOINT_1) { - log_group_header_read(group, field); + log_header_read(field); if (static_cast<uint32_t>(ut_fold_binary(buf, CHECKSUM_1)) != mach_read_from_4(buf + CHECKSUM_1) @@ -1125,21 +1112,20 @@ recv_find_max_checkpoint_0(log_group_t** max_group, ulint* max_field) mach_read_from_8(buf + LOG_CHECKPOINT_LSN))); if (checkpoint_no >= max_no) { - *max_group = group; + found = true; *max_field = field; max_no = checkpoint_no; - group->state = LOG_GROUP_OK; - - group->lsn = mach_read_from_8( - buf + LOG_CHECKPOINT_LSN); - group->lsn_offset = static_cast<ib_uint64_t>( - mach_read_from_4(buf + OFFSET_HIGH32)) << 32 - | mach_read_from_4(buf + OFFSET_LOW32); + log_sys.log.set_lsn(mach_read_from_8( + buf + LOG_CHECKPOINT_LSN)); + log_sys.log.set_lsn_offset( + lsn_t(mach_read_from_4(buf + OFFSET_HIGH32)) + << 32 + | mach_read_from_4(buf + OFFSET_LOW32)); } } - if (*max_group != NULL) { + if (found) { return(DB_SUCCESS); } @@ -1160,34 +1146,27 @@ recv_find_max_checkpoint_0(log_group_t** max_group, ulint* max_field) static dberr_t recv_log_format_0_recover(lsn_t lsn, bool crypt) { log_mutex_enter(); - log_group_t* group = &log_sys->log; - const lsn_t source_offset - = log_group_calc_lsn_offset(lsn, group); + const lsn_t source_offset = log_sys.log.calc_lsn_offset(lsn); log_mutex_exit(); - const ulint page_no - = (ulint) (source_offset / univ_page_size.physical()); - byte* buf = log_sys->buf; + const ulint page_no = ulint(source_offset >> srv_page_size_shift); + byte* buf = log_sys.buf; static const char* NO_UPGRADE_RECOVERY_MSG = "Upgrade after a crash is not supported." " This redo log was created before MariaDB 10.2.2"; - static const char* NO_UPGRADE_RTFM_MSG = - ". Please follow the instructions at " - "https://mariadb.com/kb/en/library/upgrading/"; fil_io(IORequestLogRead, true, page_id_t(SRV_LOG_SPACE_FIRST_ID, page_no), univ_page_size, - (ulint) ((source_offset & ~(OS_FILE_LOG_BLOCK_SIZE - 1)) - % univ_page_size.physical()), - OS_FILE_LOG_BLOCK_SIZE, buf, NULL); + ulint((source_offset & ~(OS_FILE_LOG_BLOCK_SIZE - 1)) + & (srv_page_size - 1)), + OS_FILE_LOG_BLOCK_SIZE, buf, NULL); if (log_block_calc_checksum_format_0(buf) != log_block_get_checksum(buf) && !log_crypt_101_read_block(buf)) { ib::error() << NO_UPGRADE_RECOVERY_MSG - << ", and it appears corrupted" - << NO_UPGRADE_RTFM_MSG; + << ", and it appears corrupted."; return(DB_CORRUPTION); } @@ -1195,12 +1174,11 @@ static dberr_t recv_log_format_0_recover(lsn_t lsn, bool crypt) == (source_offset & (OS_FILE_LOG_BLOCK_SIZE - 1))) { } else if (crypt) { ib::error() << "Cannot decrypt log for upgrading." - " The encrypted log was created before MariaDB 10.2.2" - << NO_UPGRADE_RTFM_MSG; + " The encrypted log was created" + " before MariaDB 10.2.2."; return DB_ERROR; } else { - ib::error() << NO_UPGRADE_RECOVERY_MSG - << NO_UPGRADE_RTFM_MSG; + ib::error() << NO_UPGRADE_RECOVERY_MSG << "."; return(DB_ERROR); } @@ -1209,29 +1187,27 @@ static dberr_t recv_log_format_0_recover(lsn_t lsn, bool crypt) recv_sys->parse_start_lsn = recv_sys->recovered_lsn = recv_sys->scanned_lsn = recv_sys->mlog_checkpoint_lsn = lsn; - log_sys->last_checkpoint_lsn = log_sys->next_checkpoint_lsn - = log_sys->lsn = log_sys->write_lsn - = log_sys->current_flush_lsn = log_sys->flushed_to_disk_lsn + log_sys.last_checkpoint_lsn = log_sys.next_checkpoint_lsn + = log_sys.lsn = log_sys.write_lsn + = log_sys.current_flush_lsn = log_sys.flushed_to_disk_lsn = lsn; - log_sys->next_checkpoint_no = 0; + log_sys.next_checkpoint_no = 0; return(DB_SUCCESS); } -/** Determine if a redo log from MariaDB 10.3 is clean. +/** Determine if a redo log from MariaDB 10.4 is clean. @return error code @retval DB_SUCCESS if the redo log is clean @retval DB_CORRUPTION if the redo log is corrupted @retval DB_ERROR if the redo log is not empty */ -static -dberr_t -recv_log_recover_10_3() +static dberr_t recv_log_recover_10_4() { - log_group_t* group = &log_sys->log; - const lsn_t lsn = group->lsn; - const lsn_t source_offset = log_group_calc_lsn_offset(lsn, group); + ut_ad(!log_sys.is_encrypted()); + const lsn_t lsn = log_sys.log.get_lsn(); + const lsn_t source_offset = log_sys.log.calc_lsn_offset(lsn); const ulint page_no = (ulint) (source_offset / univ_page_size.physical()); - byte* buf = log_sys->buf; + byte* buf = log_sys.buf; fil_io(IORequestLogRead, true, page_id_t(SRV_LOG_SPACE_FIRST_ID, page_no), @@ -1241,11 +1217,7 @@ recv_log_recover_10_3() OS_FILE_LOG_BLOCK_SIZE, buf, NULL); if (log_block_calc_checksum(buf) != log_block_get_checksum(buf)) { - return(DB_CORRUPTION); - } - - if (group->is_encrypted()) { - log_crypt(buf, lsn, OS_FILE_LOG_BLOCK_SIZE, true); + return DB_CORRUPTION; } /* On a clean shutdown, the redo log will be logically empty @@ -1253,7 +1225,7 @@ recv_log_recover_10_3() if (log_block_get_data_len(buf) != (source_offset & (OS_FILE_LOG_BLOCK_SIZE - 1))) { - return(DB_ERROR); + return DB_ERROR; } /* Mark the redo log for downgrading. */ @@ -1261,12 +1233,12 @@ recv_log_recover_10_3() recv_sys->parse_start_lsn = recv_sys->recovered_lsn = recv_sys->scanned_lsn = recv_sys->mlog_checkpoint_lsn = lsn; - log_sys->last_checkpoint_lsn = log_sys->next_checkpoint_lsn - = log_sys->lsn = log_sys->write_lsn - = log_sys->current_flush_lsn = log_sys->flushed_to_disk_lsn + log_sys.last_checkpoint_lsn = log_sys.next_checkpoint_lsn + = log_sys.lsn = log_sys.write_lsn + = log_sys.current_flush_lsn = log_sys.flushed_to_disk_lsn = lsn; - log_sys->next_checkpoint_no = 0; - return(DB_SUCCESS); + log_sys.next_checkpoint_no = 0; + return DB_SUCCESS; } /** Find the latest checkpoint in the log header. @@ -1275,29 +1247,24 @@ recv_log_recover_10_3() dberr_t recv_find_max_checkpoint(ulint* max_field) { - log_group_t* group; ib_uint64_t max_no; ib_uint64_t checkpoint_no; ulint field; byte* buf; - group = &log_sys->log; - max_no = 0; *max_field = 0; - buf = log_sys->checkpoint_buf; + buf = log_sys.checkpoint_buf; - group->state = LOG_GROUP_CORRUPTED; - - log_group_header_read(group, 0); + log_header_read(0); /* Check the header page checksum. There was no checksum in the first redo log format (version 0). */ - group->format = mach_read_from_4(buf + LOG_HEADER_FORMAT); - group->subformat = group->format + log_sys.log.format = mach_read_from_4(buf + LOG_HEADER_FORMAT); + log_sys.log.subformat = log_sys.log.format != LOG_HEADER_FORMAT_3_23 ? mach_read_from_4(buf + LOG_HEADER_SUBFORMAT) : 0; - if (group->format != 0 + if (log_sys.log.format != LOG_HEADER_FORMAT_3_23 && !recv_check_log_header_checksum(buf)) { ib::error() << "Invalid redo log header checksum."; return(DB_CORRUPTION); @@ -1309,35 +1276,27 @@ recv_find_max_checkpoint(ulint* max_field) /* Ensure that the string is NUL-terminated. */ creator[LOG_HEADER_CREATOR_END - LOG_HEADER_CREATOR] = 0; - switch (group->format) { - case 0: - return(recv_find_max_checkpoint_0(&group, max_field)); + switch (log_sys.log.format) { + case LOG_HEADER_FORMAT_3_23: + return(recv_find_max_checkpoint_0(max_field)); case LOG_HEADER_FORMAT_10_2: case LOG_HEADER_FORMAT_10_2 | LOG_HEADER_FORMAT_ENCRYPTED: - case LOG_HEADER_FORMAT_10_3: - case LOG_HEADER_FORMAT_10_3 | LOG_HEADER_FORMAT_ENCRYPTED: + case LOG_HEADER_FORMAT_CURRENT: + case LOG_HEADER_FORMAT_CURRENT | LOG_HEADER_FORMAT_ENCRYPTED: case LOG_HEADER_FORMAT_10_4: /* We can only parse the unencrypted LOG_HEADER_FORMAT_10_4. The encrypted format uses a larger redo log block trailer. */ break; default: ib::error() << "Unsupported redo log format." - " The redo log was created" - " with " << creator << - ". Please follow the instructions at " - "https://mariadb.com/kb/en/library/upgrading/"; - /* Do not issue a message about a possibility - to cleanly shut down the newer server version - and to remove the redo logs, because the - format of the system data structures may - radically change after MySQL 5.7. */ + " The redo log was created with " << creator << "."; return(DB_ERROR); } for (field = LOG_CHECKPOINT_1; field <= LOG_CHECKPOINT_2; field += LOG_CHECKPOINT_2 - LOG_CHECKPOINT_1) { - log_group_header_read(group, field); + log_header_read(field); const ulint crc32 = log_block_calc_checksum_crc32(buf); const ulint cksum = log_block_get_checksum(buf); @@ -1352,7 +1311,7 @@ recv_find_max_checkpoint(ulint* max_field) continue; } - if (group->is_encrypted() + if (log_sys.is_encrypted() && !log_crypt_read_checkpoint_buf(buf)) { ib::error() << "Reading checkpoint" " encryption info failed."; @@ -1370,12 +1329,11 @@ recv_find_max_checkpoint(ulint* max_field) if (checkpoint_no >= max_no) { *max_field = field; max_no = checkpoint_no; - group->state = LOG_GROUP_OK; - group->lsn = mach_read_from_8( - buf + LOG_CHECKPOINT_LSN); - group->lsn_offset = mach_read_from_8( - buf + LOG_CHECKPOINT_OFFSET); - log_sys->next_checkpoint_no = checkpoint_no; + log_sys.log.set_lsn(mach_read_from_8( + buf + LOG_CHECKPOINT_LSN)); + log_sys.log.set_lsn_offset(mach_read_from_8( + buf + LOG_CHECKPOINT_OFFSET)); + log_sys.next_checkpoint_no = checkpoint_no; } } @@ -1392,22 +1350,8 @@ recv_find_max_checkpoint(ulint* max_field) return(DB_ERROR); } - switch (group->format) { - case LOG_HEADER_FORMAT_10_3: - case LOG_HEADER_FORMAT_10_3 | LOG_HEADER_FORMAT_ENCRYPTED: - if (group->subformat == 1) { - /* 10.2 with new crash-safe TRUNCATE */ - break; - } - /* fall through */ - case LOG_HEADER_FORMAT_10_4: - if (srv_operation == SRV_OPERATION_BACKUP) { - ib::error() - << "Incompatible redo log format." - " The redo log was created with " << creator; - return DB_ERROR; - } - dberr_t err = recv_log_recover_10_3(); + if (log_sys.log.format == LOG_HEADER_FORMAT_10_4) { + dberr_t err = recv_log_recover_10_4(); if (err != DB_SUCCESS) { ib::error() << "Downgrade after a crash is not supported." @@ -1415,10 +1359,10 @@ recv_find_max_checkpoint(ulint* max_field) << (err == DB_ERROR ? "." : ", and it appears corrupted."); } - return(err); + return err; } - return(DB_SUCCESS); + return DB_SUCCESS; } /** Try to parse a single log record body and also applies it if @@ -1750,18 +1694,22 @@ parse_log: ptr = trx_undo_parse_add_undo_rec(ptr, end_ptr, page); break; case MLOG_UNDO_ERASE_END: - ut_ad(!page || page_type == FIL_PAGE_UNDO_LOG); - ptr = trx_undo_parse_erase_page_end(ptr, end_ptr, page, mtr); + if (page) { + ut_ad(page_type == FIL_PAGE_UNDO_LOG); + trx_undo_erase_page_end(page); + } break; case MLOG_UNDO_INIT: /* Allow anything in page_type when creating a page. */ - ptr = trx_undo_parse_page_init(ptr, end_ptr, page, mtr); + ptr = trx_undo_parse_page_init(ptr, end_ptr, page); break; - case MLOG_UNDO_HDR_CREATE: case MLOG_UNDO_HDR_REUSE: ut_ad(!page || page_type == FIL_PAGE_UNDO_LOG); - ptr = trx_undo_parse_page_header(type, ptr, end_ptr, - page, mtr); + ptr = trx_undo_parse_page_header_reuse(ptr, end_ptr, page); + break; + case MLOG_UNDO_HDR_CREATE: + ut_ad(!page || page_type == FIL_PAGE_UNDO_LOG); + ptr = trx_undo_parse_page_header(ptr, end_ptr, page, mtr); break; case MLOG_REC_MIN_MARK: case MLOG_COMP_REC_MIN_MARK: ut_ad(!page || fil_page_type_is_index(page_type)); @@ -1828,9 +1776,15 @@ parse_log: ptr, end_ptr, page, page_zip, index); } break; + case MLOG_ZIP_WRITE_TRX_ID: + /* This must be a clustered index leaf page. */ + ut_ad(!page || page_type == FIL_PAGE_INDEX); + ptr = page_zip_parse_write_trx_id(ptr, end_ptr, + page, page_zip); + break; case MLOG_FILE_WRITE_CRYPT_DATA: dberr_t err; - ptr = const_cast<byte*>(fil_parse_write_crypt_data(ptr, end_ptr, block, &err)); + ptr = const_cast<byte*>(fil_parse_write_crypt_data(ptr, end_ptr, &err)); if (err != DB_SUCCESS) { recv_sys->found_corrupt_log = TRUE; @@ -1942,13 +1896,13 @@ recv_add_to_hash_table( ut_ad(type != MLOG_INDEX_LOAD); ut_ad(type != MLOG_TRUNCATE); - len = rec_end - body; + len = ulint(rec_end - body); recv = static_cast<recv_t*>( mem_heap_alloc(recv_sys->heap, sizeof(recv_t))); recv->type = type; - recv->len = rec_end - body; + recv->len = ulint(rec_end - body); recv->start_lsn = start_lsn; recv->end_lsn = end_lsn; @@ -1985,13 +1939,13 @@ recv_add_to_hash_table( prev_field = &(recv->data); - /* Store the log record body in chunks of less than UNIV_PAGE_SIZE: + /* Store the log record body in chunks of less than srv_page_size: recv_sys->heap grows into the buffer pool, and bigger chunks could not be allocated */ while (rec_end > body) { - len = rec_end - body; + len = ulint(rec_end - body); if (len > RECV_DATA_BLOCK_SIZE) { len = RECV_DATA_BLOCK_SIZE; @@ -2084,6 +2038,7 @@ static void recv_recover_page(buf_block_t* block, mtr_t& mtr, } lsn_t start_lsn = 0, end_lsn = 0; + fil_space_t* space; if (srv_is_tablespace_truncated(recv_addr->space)) { /* The table will be truncated after applying @@ -2091,11 +2046,16 @@ static void recv_recover_page(buf_block_t* block, mtr_t& mtr, goto skip_log; } + space = fil_space_acquire(recv_addr->space); + if (!space) { + goto skip_log; + } + for (recv_t* recv = UT_LIST_GET_FIRST(recv_addr->rec_list); recv; recv = UT_LIST_GET_NEXT(rec_list, recv)) { ut_ad(recv->start_lsn); end_lsn = recv->end_lsn; - ut_ad(end_lsn <= log_sys->log.scanned_lsn); + ut_ad(end_lsn <= log_sys.log.scanned_lsn); if (recv->start_lsn < page_lsn) { /* Ignore this record, because there are later changes @@ -2109,8 +2069,7 @@ static void recv_recover_page(buf_block_t* block, mtr_t& mtr, << get_mlog_string(recv->type) << " LSN " << recv->start_lsn << " < " << init_lsn); - } else if (srv_was_tablespace_truncated( - fil_space_get(recv_addr->space)) + } else if (srv_was_tablespace_truncated(space) && recv->start_lsn < truncate_t::get_truncated_tablespace_init_lsn( recv_addr->space)) { @@ -2172,6 +2131,8 @@ static void recv_recover_page(buf_block_t* block, mtr_t& mtr, } } + space->release(); + skip_log: #ifdef UNIV_ZIP_DEBUG ut_ad(!fil_page_index_page_check(page) @@ -2436,7 +2397,7 @@ skip: if (space->enable_lsn) { do_read: - fil_space_release(space); + space->release(); recv_addr->state = RECV_NOT_PROCESSED; goto apply; } @@ -2483,7 +2444,7 @@ do_read: ut_ad(mtr.has_committed()); } - fil_space_release(space); + space->release(); } } } @@ -2656,7 +2617,7 @@ recv_parse_log_rec( fil_space_set_recv_size(*space, size); } - return(new_ptr - ptr); + return ulint(new_ptr - ptr); } /*******************************************************//** @@ -2849,9 +2810,7 @@ loop: /* Do nothing */ break; case MLOG_CHECKPOINT: -#if SIZE_OF_MLOG_CHECKPOINT != 1 + 8 -# error SIZE_OF_MLOG_CHECKPOINT != 1 + 8 -#endif + compile_time_assert(SIZE_OF_MLOG_CHECKPOINT == 1 + 8); lsn = mach_read_from_8(ptr + 1); if (UNIV_UNLIKELY(srv_print_verbose_log == 2)) { @@ -3382,7 +3341,6 @@ func_exit: /** Scans log from a buffer and stores new log data to the parsing buffer. Parses and hashes the log records if new data found. -@param[in,out] group log group @param[in] checkpoint_lsn latest checkpoint log sequence number @param[in,out] contiguous_lsn log sequence number until which all redo log has been scanned @@ -3392,7 +3350,6 @@ can be applied to the tablespaces static bool recv_group_scan_log_recs( - log_group_t* group, lsn_t checkpoint_lsn, lsn_t* contiguous_lsn, bool last_phase) @@ -3421,12 +3378,12 @@ recv_group_scan_log_recs( lsn_t end_lsn; store_t store_to_hash = recv_sys->mlog_checkpoint_lsn == 0 ? STORE_NO : (last_phase ? STORE_IF_EXISTS : STORE_YES); - ulint available_mem = UNIV_PAGE_SIZE + ulint available_mem = srv_page_size * (buf_pool_get_n_pages() - (recv_n_pool_free_frames * srv_buf_pool_instances)); - group->scanned_lsn = end_lsn = *contiguous_lsn = ut_uint64_align_down( - *contiguous_lsn, OS_FILE_LOG_BLOCK_SIZE); + log_sys.log.scanned_lsn = end_lsn = *contiguous_lsn = + ut_uint64_align_down(*contiguous_lsn, OS_FILE_LOG_BLOCK_SIZE); do { if (last_phase && store_to_hash == STORE_NO) { @@ -3441,15 +3398,13 @@ recv_group_scan_log_recs( start_lsn = ut_uint64_align_down(end_lsn, OS_FILE_LOG_BLOCK_SIZE); end_lsn = start_lsn; - log_group_read_log_seg( - log_sys->buf, group, &end_lsn, - start_lsn + RECV_SCAN_SIZE); + log_sys.log.read_log_seg(&end_lsn, start_lsn + RECV_SCAN_SIZE); } while (end_lsn != start_lsn && !recv_scan_log_recs( - available_mem, &store_to_hash, log_sys->buf, + available_mem, &store_to_hash, log_sys.buf, checkpoint_lsn, start_lsn, end_lsn, - contiguous_lsn, &group->scanned_lsn)); + contiguous_lsn, &log_sys.log.scanned_lsn)); if (recv_sys->found_corrupt_log || recv_sys->found_corrupt_fs) { DBUG_RETURN(false); @@ -3457,7 +3412,7 @@ recv_group_scan_log_recs( DBUG_PRINT("ib_log", ("%s " LSN_PF " completed", last_phase ? "rescan" : "scan", - group->scanned_lsn)); + log_sys.log.scanned_lsn)); DBUG_RETURN(store_to_hash == STORE_NO); } @@ -3666,55 +3621,35 @@ recv_recovery_from_checkpoint_start(lsn_t flush_lsn) log_mutex_enter(); - /* Look for the latest checkpoint from any of the log groups */ - err = recv_find_max_checkpoint(&max_cp_field); if (err != DB_SUCCESS) { -skip_apply: + + srv_start_lsn = recv_sys->recovered_lsn = log_sys.lsn; log_mutex_exit(); return(err); } - switch (log_sys->log.format) { - case 0: - break; - case LOG_HEADER_FORMAT_10_2: - case LOG_HEADER_FORMAT_10_2 | LOG_HEADER_FORMAT_ENCRYPTED: - break; - case LOG_HEADER_FORMAT_10_3: - case LOG_HEADER_FORMAT_10_3 | LOG_HEADER_FORMAT_ENCRYPTED: - if (log_sys->log.subformat == 1) { - /* 10.2 with new crash-safe TRUNCATE */ - break; - } - /* fall through */ - default: - /* This must be a clean log from a newer version. */ - goto skip_apply; - } - - log_group_header_read(&log_sys->log, max_cp_field); + log_header_read(max_cp_field); - buf = log_sys->checkpoint_buf; + buf = log_sys.checkpoint_buf; checkpoint_lsn = mach_read_from_8(buf + LOG_CHECKPOINT_LSN); checkpoint_no = mach_read_from_8(buf + LOG_CHECKPOINT_NO); - /* Start reading the log groups from the checkpoint lsn up. The - variable contiguous_lsn contains an lsn up to which the log is - known to be contiguously written to all log groups. */ - + /* Start reading the log from the checkpoint lsn. The variable + contiguous_lsn contains an lsn up to which the log is known to + be contiguously written. */ recv_sys->mlog_checkpoint_lsn = 0; - ut_ad(RECV_SCAN_SIZE <= log_sys->buf_size); + ut_ad(RECV_SCAN_SIZE <= srv_log_buffer_size); const lsn_t end_lsn = mach_read_from_8( buf + LOG_CHECKPOINT_END_LSN); ut_ad(recv_sys->n_addrs == 0); contiguous_lsn = checkpoint_lsn; - switch (log_sys->log.format) { + switch (log_sys.log.format) { case 0: log_mutex_exit(); return recv_log_format_0_recover(checkpoint_lsn, @@ -3733,9 +3668,7 @@ skip_apply: } /* Look for MLOG_CHECKPOINT. */ - log_group_t* group = &log_sys->log; - recv_group_scan_log_recs(group, checkpoint_lsn, &contiguous_lsn, - false); + recv_group_scan_log_recs(checkpoint_lsn, &contiguous_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); @@ -3752,7 +3685,7 @@ skip_apply: } if (recv_sys->mlog_checkpoint_lsn == 0) { - lsn_t scan_lsn = group->scanned_lsn; + lsn_t scan_lsn = log_sys.log.scanned_lsn; if (!srv_read_only_mode && scan_lsn != checkpoint_lsn) { log_mutex_exit(); ib::error err; @@ -3765,12 +3698,12 @@ skip_apply: return(DB_ERROR); } - group->scanned_lsn = checkpoint_lsn; + log_sys.log.scanned_lsn = checkpoint_lsn; rescan = false; } else { contiguous_lsn = checkpoint_lsn; rescan = recv_group_scan_log_recs( - group, checkpoint_lsn, &contiguous_lsn, false); + checkpoint_lsn, &contiguous_lsn, false); if ((recv_sys->found_corrupt_log && !srv_force_recovery) || recv_sys->found_corrupt_fs) { @@ -3816,7 +3749,7 @@ skip_apply: } } - log_sys->lsn = recv_sys->recovered_lsn; + log_sys.lsn = recv_sys->recovered_lsn; if (recv_needed_recovery) { bool missing_tablespace = false; @@ -3843,8 +3776,7 @@ skip_apply: lsn_t recent_stored_lsn = recv_sys->last_stored_lsn; rescan = recv_group_scan_log_recs( - group, checkpoint_lsn, - &recent_stored_lsn, false); + checkpoint_lsn, &recent_stored_lsn, false); ut_ad(!recv_sys->found_corrupt_fs); @@ -3877,8 +3809,8 @@ skip_apply: if (rescan) { contiguous_lsn = checkpoint_lsn; - recv_group_scan_log_recs(group, checkpoint_lsn, - &contiguous_lsn, true); + recv_group_scan_log_recs( + checkpoint_lsn, &contiguous_lsn, true); if ((recv_sys->found_corrupt_log && !srv_force_recovery) @@ -3891,12 +3823,11 @@ skip_apply: ut_ad(!rescan || recv_sys->n_addrs == 0); } - /* We currently have only one log group */ - - if (group->scanned_lsn < checkpoint_lsn - || group->scanned_lsn < recv_max_page_lsn) { + if (log_sys.log.scanned_lsn < checkpoint_lsn + || log_sys.log.scanned_lsn < recv_max_page_lsn) { - ib::error() << "We scanned the log up to " << group->scanned_lsn + ib::error() << "We scanned the log up to " + << log_sys.log.scanned_lsn << ". A checkpoint was at " << checkpoint_lsn << " and" " the maximum LSN on a database page was " << recv_max_page_lsn << ". It is possible that the" @@ -3912,11 +3843,8 @@ skip_apply: return(DB_ERROR); } - /* Synchronize the uncorrupted log groups to the most up-to-date log - group; we also copy checkpoint info to groups */ - - log_sys->next_checkpoint_lsn = checkpoint_lsn; - log_sys->next_checkpoint_no = checkpoint_no + 1; + log_sys.next_checkpoint_lsn = checkpoint_lsn; + log_sys.next_checkpoint_no = checkpoint_no + 1; recv_synchronize_groups(); @@ -3926,24 +3854,24 @@ skip_apply: srv_start_lsn = recv_sys->recovered_lsn; } - log_sys->buf_free = (ulint) log_sys->lsn % OS_FILE_LOG_BLOCK_SIZE; - log_sys->buf_next_to_write = log_sys->buf_free; - log_sys->write_lsn = log_sys->lsn; + log_sys.buf_free = ulong(log_sys.lsn % OS_FILE_LOG_BLOCK_SIZE); + log_sys.buf_next_to_write = log_sys.buf_free; + log_sys.write_lsn = log_sys.lsn; - log_sys->last_checkpoint_lsn = checkpoint_lsn; + log_sys.last_checkpoint_lsn = checkpoint_lsn; if (!srv_read_only_mode && srv_operation == SRV_OPERATION_NORMAL) { /* Write a MLOG_CHECKPOINT marker as the first thing, before generating any other redo log. This ensures that subsequent crash recovery will be possible even if the server were killed soon after this. */ - fil_names_clear(log_sys->last_checkpoint_lsn, true); + fil_names_clear(log_sys.last_checkpoint_lsn, true); } MONITOR_SET(MONITOR_LSN_CHECKPOINT_AGE, - log_sys->lsn - log_sys->last_checkpoint_lsn); + log_sys.lsn - log_sys.last_checkpoint_lsn); - log_sys->next_checkpoint_no = ++checkpoint_no; + log_sys.next_checkpoint_no = ++checkpoint_no; mutex_enter(&recv_sys->mutex); @@ -4020,7 +3948,6 @@ recv_recovery_rollback_active(void) /* Drop partially created indexes. */ row_merge_drop_temp_indexes(); /* Drop garbage tables. */ - if (srv_safe_truncate) row_mysql_drop_garbage_tables(); /* Drop any auxiliary tables that were not dropped when the @@ -4032,8 +3959,8 @@ recv_recovery_rollback_active(void) /* Rollback the uncommitted transactions which have no user session */ - trx_rollback_or_clean_is_active = true; - os_thread_create(trx_rollback_or_clean_all_recovered, 0, 0); + trx_rollback_is_active = true; + os_thread_create(trx_rollback_all_recovered, 0, 0); } } @@ -4223,6 +4150,9 @@ static const char* get_mlog_string(mlog_id_t type) case MLOG_ZIP_PAGE_REORGANIZE: return("MLOG_ZIP_PAGE_REORGANIZE"); + case MLOG_ZIP_WRITE_TRX_ID: + return("MLOG_ZIP_WRITE_TRX_ID"); + case MLOG_FILE_RENAME2: return("MLOG_FILE_RENAME2"); |