summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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;