diff options
author | Thirunarayanan Balathandayuthapani <thiru@mariadb.com> | 2023-01-06 11:14:54 +0530 |
---|---|---|
committer | Thirunarayanan Balathandayuthapani <thiru@mariadb.com> | 2023-01-06 11:14:54 +0530 |
commit | f27b11d61e19c410fbd542255bb0faa6a6d3e197 (patch) | |
tree | 639a095251434d3df48d3c65333febdea658b939 | |
parent | cfaf47a4d4d740bbf561898a4c96670e7df4d428 (diff) | |
download | mariadb-git-bb-10.11-MDEV-30179.tar.gz |
MDEV-30179 mariabackup --backup fails with FATAL ERROR: ... failedbb-10.11-MDEV-30179
to copy datafile
- Mariabackup fails to copy the undo log tablespace when it undergoes
truncation. So Mariabackup should detect the redo log which does
undo tablespace truncation and also backup should read the minimum
file size of the tablespace and ignore the error while reading.
- Throw error when innodb undo tablespace read failed, but backup
doesn't find the redo log for undo tablespace truncation
-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; |