diff options
-rw-r--r-- | extra/mariabackup/fil_cur.cc | 25 | ||||
-rw-r--r-- | extra/mariabackup/xtrabackup.cc | 43 | ||||
-rw-r--r-- | storage/innobase/include/log0recv.h | 5 | ||||
-rw-r--r-- | storage/innobase/log/log0recv.cc | 4 |
4 files changed, 73 insertions, 4 deletions
diff --git a/extra/mariabackup/fil_cur.cc b/extra/mariabackup/fil_cur.cc index 7b268df2364..cbe6c69f8dc 100644 --- a/extra/mariabackup/fil_cur.cc +++ b/extra/mariabackup/fil_cur.cc @@ -365,6 +365,7 @@ xb_fil_cur_result_t xb_fil_cur_read(xb_fil_cur_t* cursor, ib_int64_t to_read; const ulint page_size = cursor->page_size; bool defer = false; + static uint32_t n_read_undo = 0; xb_ad(!cursor->is_system() || page_size == srv_page_size); cursor->read_filter->get_next_batch(&cursor->read_filter_ctxt, @@ -374,6 +375,7 @@ xb_fil_cur_result_t xb_fil_cur_read(xb_fil_cur_t* cursor, return(XB_FIL_CUR_EOF); } +reinit_buf: if (to_read > (ib_int64_t) cursor->buf_size) { to_read = (ib_int64_t) cursor->buf_size; } @@ -416,8 +418,27 @@ read_retry: if (os_file_read(IORequestRead, cursor->file, cursor->buf, offset, (ulint) to_read, nullptr) != DB_SUCCESS) { - ret = XB_FIL_CUR_ERROR; - goto func_exit; + if (!srv_is_undo_tablespace(cursor->space_id)) { + ret = XB_FIL_CUR_ERROR; + goto func_exit; + } + + if (cursor->buf_page_no + >= SRV_UNDO_TABLESPACE_SIZE_IN_PAGES) { + ret = XB_FIL_CUR_SKIP; + goto func_exit; + } + + to_read = SRV_UNDO_TABLESPACE_SIZE_IN_PAGES * page_size; + + if (n_read_undo > 1) { + ret = XB_FIL_CUR_ERROR; + goto func_exit; + } + + n_read_undo++; + space->release(); + goto reinit_buf; } defer = UT_LIST_GET_FIRST(space->chain)->deferred; diff --git a/extra/mariabackup/xtrabackup.cc b/extra/mariabackup/xtrabackup.cc index 6e3ab375eb8..4351644314c 100644 --- a/extra/mariabackup/xtrabackup.cc +++ b/extra/mariabackup/xtrabackup.cc @@ -241,6 +241,9 @@ long innobase_file_io_threads = 4; ulong innobase_read_io_threads = 4; ulong innobase_write_io_threads = 4; +/** Store the failed read of undo tablespace ids */ +std::set<space_id_t> fail_undo_ids; + longlong innobase_page_size = (1LL << 14); /* 16KB */ char* innobase_buffer_pool_filename = NULL; @@ -406,6 +409,9 @@ used to indicate whether the given deferred tablespace can be reconstructed. */ static std::set<space_id_t> first_page_init_ids; +/** Store the space ids of truncated undo log tablespaces */ +static std::set<space_id_t> undo_trunc_ids; + // Convert non-null terminated filename to space name static std::string filename_to_spacename(const void *filename, size_t len); @@ -920,6 +926,11 @@ static void backup_first_page_op(space_id_t space_id) first_page_init_ids.insert(space_id); } +static void backup_undo_trunc(uint32_t space_id) +{ + undo_trunc_ids.insert(space_id); +} + /* Retrieve default data directory, to be used with --copy-back. @@ -2912,11 +2923,20 @@ static my_bool xtrabackup_copy_datafile(fil_node_t *node, uint thread_n, } /* The main copy loop */ - while ((res = xb_fil_cur_read(&cursor, corrupted_pages)) == - XB_FIL_CUR_SUCCESS) { + while (1) { + res = xb_fil_cur_read(&cursor, corrupted_pages); + if (res == XB_FIL_CUR_ERROR || res == XB_FIL_CUR_EOF) { + break; + } + if (!write_filter.process(&write_filt_ctxt, dstfile)) { goto error; } + + if (res == XB_FIL_CUR_SKIP) { + fail_undo_ids.insert(cursor.space_id); + break; + } } if (res == XB_FIL_CUR_ERROR) { @@ -4386,6 +4406,22 @@ static bool xtrabackup_backup_low() dst_log_file = NULL; + std::vector<uint32_t> failed_ids; + std::set_difference( + fail_undo_ids.begin(), fail_undo_ids.end(), + undo_trunc_ids.begin(), undo_trunc_ids.end(), + std::inserter(failed_ids, failed_ids.begin())); + + + for (auto it = failed_ids.begin(); it != failed_ids.end(); + it++) { + msg("mariabackup: Failed to read undo log " + "tablespace space id %d and there is no undo " + "tablespace truncation redo record.", + *it); + return false; + } + if(!xtrabackup_incremental) { strcpy(metadata_type, "full-backuped"); metadata_from_lsn = 0; @@ -4460,6 +4496,7 @@ static bool xtrabackup_backup_func() srv_operation = SRV_OPERATION_BACKUP; log_file_op = backup_file_op; first_page_init = backup_first_page_op; + undo_space_trunc = backup_undo_trunc; metadata_to_lsn = 0; /* initialize components */ @@ -4475,6 +4512,7 @@ fail: log_file_op = NULL; first_page_init = NULL; + undo_space_trunc = NULL; if (dst_log_file) { ds_close(dst_log_file); dst_log_file = NULL; @@ -4711,6 +4749,7 @@ fail: innodb_shutdown(); log_file_op = NULL; first_page_init = NULL; + undo_space_trunc = NULL; pthread_cond_destroy(&scanned_lsn_cond); if (!corrupted_pages.empty()) { ut_ad(opt_log_innodb_page_corruption); diff --git a/storage/innobase/include/log0recv.h b/storage/innobase/include/log0recv.h index c661c52905b..a4b53c7b8a0 100644 --- a/storage/innobase/include/log0recv.h +++ b/storage/innobase/include/log0recv.h @@ -75,6 +75,11 @@ extern void (*log_file_op)(uint32_t space_id, int type, @param space_id tablespace identifier */ extern void (*first_page_init)(uint32_t space_id); +/** Report an operation which does undo log tablespace truncation +during backup +@param space_id undo tablespace identifier */ +extern void (*undo_space_trunc)(uint32_t space_id); + /** Stored redo log record */ struct log_rec_t { diff --git a/storage/innobase/log/log0recv.cc b/storage/innobase/log/log0recv.cc index ce17a4e6b9e..ea08a632bcb 100644 --- a/storage/innobase/log/log0recv.cc +++ b/storage/innobase/log/log0recv.cc @@ -1017,6 +1017,8 @@ void (*log_file_op)(uint32_t space_id, int type, void (*first_page_init)(uint32_t space_id); +void (*undo_space_trunc)(uint32_t space_id); + /** Information about initializing page contents during redo log processing. FIXME: Rely on recv_sys.pages! */ class mlog_init_t @@ -2570,6 +2572,8 @@ inline recv_sys_t::parse_mtr_result recv_sys_t::parse(store_t store, source &l) TRX_SYS_MAX_UNDO_SPACES, "compatibility"); truncated_undo_spaces[space_id - srv_undo_space_id_start]= { lsn, page_no }; + if (undo_space_trunc) + undo_space_trunc(space_id); #endif last_offset= 1; /* the next record must not be same_page */ continue; |