summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThirunarayanan Balathandayuthapani <thiru@mariadb.com>2023-01-06 11:14:54 +0530
committerThirunarayanan Balathandayuthapani <thiru@mariadb.com>2023-01-06 11:14:54 +0530
commitf27b11d61e19c410fbd542255bb0faa6a6d3e197 (patch)
tree639a095251434d3df48d3c65333febdea658b939
parentcfaf47a4d4d740bbf561898a4c96670e7df4d428 (diff)
downloadmariadb-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.cc25
-rw-r--r--extra/mariabackup/xtrabackup.cc43
-rw-r--r--storage/innobase/include/log0recv.h5
-rw-r--r--storage/innobase/log/log0recv.cc4
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;