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.
This commit is contained in:
parent
1b49c89429
commit
d6f7fd6016
@ -358,9 +358,8 @@ struct ddl_tracker_t {
|
|||||||
/* For DDL operation found in redo log, */
|
/* For DDL operation found in redo log, */
|
||||||
space_id_to_name_t id_to_name;
|
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 */
|
/* Whether xtrabackup_binlog_info should be created on recovery */
|
||||||
static bool recover_binlog_info;
|
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.
|
/** Callback whenever MLOG_INDEX_LOAD happens.
|
||||||
@param[in] space_id space id to check
|
@param[in] space_id space id to check */
|
||||||
@return false */
|
static void backup_optimized_ddl_op(ulint space_id)
|
||||||
void backup_optimized_ddl_op(ulint space_id)
|
|
||||||
{
|
{
|
||||||
// TODO : handle incremental
|
// TODO : handle incremental
|
||||||
if (xtrabackup_incremental)
|
if (xtrabackup_incremental)
|
||||||
@ -631,6 +629,15 @@ void backup_optimized_ddl_op(ulint space_id)
|
|||||||
pthread_mutex_unlock(&backup_mutex);
|
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 ======== */
|
/* ======== Date copying thread context ======== */
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
@ -4240,12 +4247,13 @@ fail_before_log_copying_thread_start:
|
|||||||
/* copy log file by current position */
|
/* copy log file by current position */
|
||||||
log_copy_scanned_lsn = checkpoint_lsn_start;
|
log_copy_scanned_lsn = checkpoint_lsn_start;
|
||||||
recv_sys->recovered_lsn = log_copy_scanned_lsn;
|
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())
|
if (xtrabackup_copy_logfile())
|
||||||
goto fail_before_log_copying_thread_start;
|
goto fail_before_log_copying_thread_start;
|
||||||
|
|
||||||
log_copying_stop = os_event_create(0);
|
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);
|
os_thread_create(log_copying_thread, NULL, &log_copying_thread_id);
|
||||||
|
|
||||||
/* FLUSH CHANGED_PAGE_BITMAPS call */
|
/* 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;
|
19
mysql-test/suite/mariabackup/truncate_during_backup.test
Normal file
19
mysql-test/suite/mariabackup/truncate_during_backup.test
Normal file
@ -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. */
|
/** Moves the parsing buffer data left to the buffer start. */
|
||||||
void recv_sys_justify_left_parsing_buf();
|
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
|
@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.
|
/** Report an operation to create, delete, or rename a file during backup.
|
||||||
@param[in] space_id tablespace identifier
|
@param[in] space_id tablespace identifier
|
||||||
|
@ -169,11 +169,16 @@ typedef std::map<
|
|||||||
|
|
||||||
static recv_spaces_t recv_spaces;
|
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
|
@param[in] space_id tablespace identifier
|
||||||
*/
|
*/
|
||||||
void (*log_optimized_ddl_op)(ulint space_id);
|
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.
|
/** Report an operation to create, delete, or rename a file during backup.
|
||||||
@param[in] space_id tablespace identifier
|
@param[in] space_id tablespace identifier
|
||||||
@param[in] flags tablespace flags (NULL if not create)
|
@param[in] flags tablespace flags (NULL if not create)
|
||||||
@ -1196,6 +1201,12 @@ recv_parse_or_apply_log_rec_body(
|
|||||||
}
|
}
|
||||||
return(ptr + 8);
|
return(ptr + 8);
|
||||||
case MLOG_TRUNCATE:
|
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));
|
return(truncate_t::parse_redo_entry(ptr, end_ptr, space_id));
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
Loading…
x
Reference in New Issue
Block a user