Skip to content
Permalink
Browse files
MDEV-13564: Refuse MLOG_TRUNCATE in mariabackup
The MySQL 5.7 TRUNCATE TABLE is inherently incompatible
with hot backup, because it is creating and deleting a separate
log file, and it is not writing redo log for all changes of the
InnoDB data dictionary tables. Refuse to create a corrupted backup
if the unsafe form of TRUNCATE was executed.

Note: Undo log tablespace truncation cannot be detected easily.
Also it is incompatible with backup, for similar reasons.

xtrabackup_backup_func(): "Subscribe to" the log events before
the first invocation of xtrabackup_copy_logfile().

recv_parse_or_apply_log_rec_body(): If the function pointer
log_truncate is set, invoke it to report MLOG_TRUNCATE.
  • Loading branch information
dr-m committed Aug 16, 2018
1 parent 1b49c89 commit d6f7fd6
Show file tree
Hide file tree
Showing 5 changed files with 56 additions and 9 deletions.
@@ -358,9 +358,8 @@ struct ddl_tracker_t {
/* For DDL operation found in redo log, */
space_id_to_name_t id_to_name;
};
const space_id_t REMOVED_SPACE_ID = ULINT_MAX;
static ddl_tracker_t ddl_tracker;

static ddl_tracker_t ddl_tracker;

/* Whether xtrabackup_binlog_info should be created on recovery */
static bool recover_binlog_info;
@@ -618,9 +617,8 @@ void backup_file_op(ulint space_id, const byte* flags,


/** Callback whenever MLOG_INDEX_LOAD happens.
@param[in] space_id space id to check
@return false */
void backup_optimized_ddl_op(ulint space_id)
@param[in] space_id space id to check */
static void backup_optimized_ddl_op(ulint space_id)
{
// TODO : handle incremental
if (xtrabackup_incremental)
@@ -631,6 +629,15 @@ void backup_optimized_ddl_op(ulint space_id)
pthread_mutex_unlock(&backup_mutex);
}

/** Callback whenever MLOG_TRUNCATE happens. */
static void backup_truncate_fail()
{
msg("mariabackup: Incompatible TRUNCATE operation detected.%s\n",
opt_lock_ddl_per_table
? ""
: " Use --lock-ddl-per-table to lock all tables before backup.");
}

/* ======== Date copying thread context ======== */

typedef struct {
@@ -4240,12 +4247,13 @@ xtrabackup_backup_func()
/* copy log file by current position */
log_copy_scanned_lsn = checkpoint_lsn_start;
recv_sys->recovered_lsn = log_copy_scanned_lsn;
log_optimized_ddl_op = backup_optimized_ddl_op;
log_truncate = backup_truncate_fail;

if (xtrabackup_copy_logfile())
goto fail_before_log_copying_thread_start;

log_copying_stop = os_event_create(0);
log_optimized_ddl_op = backup_optimized_ddl_op;
os_thread_create(log_copying_thread, NULL, &log_copying_thread_id);

/* FLUSH CHANGED_PAGE_BITMAPS call */
@@ -0,0 +1,4 @@
CREATE TABLE t1 ENGINE=InnoDB SELECT 1;
DROP TABLE t1;
SET GLOBAL innodb_log_checkpoint_now=1;
SET GLOBAL innodb_log_checkpoint_now=DEFAULT;
@@ -0,0 +1,19 @@
--source include/have_debug.inc
let $targetdir=$MYSQLTEST_VARDIR/tmp/backup;
mkdir $targetdir;

CREATE TABLE t1 ENGINE=InnoDB SELECT 1;

--let after_load_tablespaces=TRUNCATE test.t1

--disable_result_log
--error 1
exec $XTRABACKUP --defaults-file=$MYSQLTEST_VARDIR/my.cnf --backup --target-dir=$targetdir --dbug=+d,mariabackup_events;
--enable_result_log

--let after_load_tablespaces=

DROP TABLE t1;
SET GLOBAL innodb_log_checkpoint_now=1;
SET GLOBAL innodb_log_checkpoint_now=DEFAULT;
rmdir $targetdir;
@@ -153,10 +153,15 @@ bool recv_parse_log_recs(lsn_t checkpoint_lsn, store_t store, bool apply);
/** Moves the parsing buffer data left to the buffer start. */
void recv_sys_justify_left_parsing_buf();

/** Report optimized DDL operation (without redo log), corresponding to MLOG_INDEX_LOAD.
/** Report optimized DDL operation (without redo log),
corresponding to MLOG_INDEX_LOAD.
@param[in] space_id tablespace identifier
*/
extern void(*log_optimized_ddl_op)(ulint space_id);
extern void (*log_optimized_ddl_op)(ulint space_id);

/** Report backup-unfriendly TRUNCATE operation (with separate log file),
corresponding to MLOG_TRUNCATE. */
extern void (*log_truncate)();

/** Report an operation to create, delete, or rename a file during backup.
@param[in] space_id tablespace identifier
@@ -169,11 +169,16 @@ typedef std::map<

static recv_spaces_t recv_spaces;

/** Report optimized DDL operation (without redo log), corresponding to MLOG_INDEX_LOAD.
/** Report optimized DDL operation (without redo log),
corresponding to MLOG_INDEX_LOAD.
@param[in] space_id tablespace identifier
*/
void (*log_optimized_ddl_op)(ulint space_id);

/** Report backup-unfriendly TRUNCATE operation (with separate log file),
corresponding to MLOG_TRUNCATE. */
void (*log_truncate)();

/** Report an operation to create, delete, or rename a file during backup.
@param[in] space_id tablespace identifier
@param[in] flags tablespace flags (NULL if not create)
@@ -1196,6 +1201,12 @@ recv_parse_or_apply_log_rec_body(
}
return(ptr + 8);
case MLOG_TRUNCATE:
if (log_truncate) {
ut_ad(srv_operation != SRV_OPERATION_NORMAL);
log_truncate();
recv_sys->found_corrupt_fs = true;
return NULL;
}
return(truncate_t::parse_redo_entry(ptr, end_ptr, space_id));

default:

0 comments on commit d6f7fd6

Please sign in to comment.