diff options
-rw-r--r-- | extra/mariabackup/xtrabackup.cc | 70 | ||||
-rw-r--r-- | mysql-test/suite/mariabackup/nolock_ddl_during_backup_end.result | 2 | ||||
-rw-r--r-- | mysql-test/suite/mariabackup/nolock_ddl_during_backup_end.test | 14 |
3 files changed, 81 insertions, 5 deletions
diff --git a/extra/mariabackup/xtrabackup.cc b/extra/mariabackup/xtrabackup.cc index d506228e8c6..9d453e5f9ad 100644 --- a/extra/mariabackup/xtrabackup.cc +++ b/extra/mariabackup/xtrabackup.cc @@ -588,7 +588,7 @@ std::string filename_to_spacename(const byte *filename, size_t len) @param[in] len length of name, in bytes @param[in] new_name new file name (NULL if not rename) @param[in] new_len length of new_name, in bytes (0 if NULL) */ -void backup_file_op(ulint space_id, const byte* flags, +static void backup_file_op(ulint space_id, const byte* flags, const byte* name, ulint len, const byte* new_name, ulint new_len) { @@ -616,19 +616,71 @@ void backup_file_op(ulint space_id, const byte* flags, } +/* + This callback is called if DDL operation is detected, + at the end of backup + + Normally, DDL operations are blocked due to FTWRL, + but in rare cases of --no-lock, they are not. + + We will abort backup in this case. +*/ +static void backup_file_op_fail(ulint space_id, const byte* flags, + const byte* name, ulint len, + const byte* new_name, ulint new_len) +{ + ut_a(opt_no_lock); + bool fail; + if (flags) { + msg("DDL tracking : create %zu \"%.*s\": %x\n", + space_id, int(len), name, mach_read_from_4(flags)); + std::string spacename = filename_to_spacename(name, len); + fail = !check_if_skip_table(spacename.c_str()); + } + else if (new_name) { + msg("DDL tracking : rename %zu \"%.*s\",\"%.*s\"\n", + space_id, int(len), name, int(new_len), new_name); + std::string spacename = filename_to_spacename(name, len); + std::string new_spacename = filename_to_spacename(new_name, new_len); + fail = !check_if_skip_table(spacename.c_str()) || !check_if_skip_table(new_spacename.c_str()); + } + else { + std::string spacename = filename_to_spacename(name, len); + fail = !check_if_skip_table(spacename.c_str()); + msg("DDL tracking : delete %zu \"%.*s\"\n", space_id, int(len), name); + } + if (fail) { + msg("ERROR : DDL operation detected in the late phase of backup." + "Backup is inconsistent. Remove --no-lock option to fix.\n"); + exit(EXIT_FAILURE); + } +} + + /** Callback whenever MLOG_INDEX_LOAD happens. @param[in] space_id space id to check */ static void backup_optimized_ddl_op(ulint space_id) { - // TODO : handle incremental - if (xtrabackup_incremental) - return; - pthread_mutex_lock(&backup_mutex); ddl_tracker.optimized_ddl.insert(space_id); pthread_mutex_unlock(&backup_mutex); } +/* + Optimized DDL callback at the end of backup that + run with --no-lock. Usually aborts the backup. +*/ +static void backup_optimized_ddl_op_fail(ulint space_id) { + ut_a(opt_no_lock); + msg("DDL tracking : optimized DDL on space %zu\n"); + if (ddl_tracker.tables_in_backup.find(space_id) != ddl_tracker.tables_in_backup.end()) { + msg("ERROR : Optimized DDL operation detected in the late phase of backup." + "Backup is inconsistent. Remove --no-lock option to fix.\n"); + exit(EXIT_FAILURE); + } +} + + /** Callback whenever MLOG_TRUNCATE happens. */ static void backup_truncate_fail() { @@ -4383,6 +4435,14 @@ void backup_fix_ddl(void) std::set<std::string> dropped_tables; std::map<std::string, std::string> renamed_tables; + /* Disable further DDL on backed up tables (only needed for --no-lock).*/ + pthread_mutex_lock(&backup_mutex); + log_file_op = backup_file_op_fail; + log_optimized_ddl_op = backup_optimized_ddl_op_fail; + pthread_mutex_unlock(&backup_mutex); + + DBUG_MARIABACKUP_EVENT("backup_fix_ddl",0); + for (space_id_to_name_t::iterator iter = ddl_tracker.tables_in_backup.begin(); iter != ddl_tracker.tables_in_backup.end(); iter++) { diff --git a/mysql-test/suite/mariabackup/nolock_ddl_during_backup_end.result b/mysql-test/suite/mariabackup/nolock_ddl_during_backup_end.result new file mode 100644 index 00000000000..1bd3052b708 --- /dev/null +++ b/mysql-test/suite/mariabackup/nolock_ddl_during_backup_end.result @@ -0,0 +1,2 @@ +CREATE TABLE t1(i int) ENGINE=INNODB; +# xtrabackup backup diff --git a/mysql-test/suite/mariabackup/nolock_ddl_during_backup_end.test b/mysql-test/suite/mariabackup/nolock_ddl_during_backup_end.test new file mode 100644 index 00000000000..f6bc51bd9a6 --- /dev/null +++ b/mysql-test/suite/mariabackup/nolock_ddl_during_backup_end.test @@ -0,0 +1,14 @@ +--source include/have_debug.inc +let $targetdir=$MYSQLTEST_VARDIR/tmp/backup; +mkdir $targetdir; + +CREATE TABLE t1(i int) ENGINE=INNODB; + +# this will table and populate it, after backup has list of tables to be copied +--let backup_fix_ddl=BEGIN NOT ATOMIC DROP TABLE test.t1;DO SLEEP(10000); END +echo # xtrabackup backup; +--disable_result_log +error 1; +exec $XTRABACKUP --defaults-file=$MYSQLTEST_VARDIR/my.cnf --backup --target-dir=$targetdir --no-lock --dbug=+d,mariabackup_events; +--enable_result_log +rmdir $targetdir; |