diff --git a/extra/mariabackup/backup_copy.cc b/extra/mariabackup/backup_copy.cc index d4a90760f6583..38b9618335749 100644 --- a/extra/mariabackup/backup_copy.cc +++ b/extra/mariabackup/backup_copy.cc @@ -1462,6 +1462,7 @@ bool backup_start(ds_ctxt *ds_data, ds_ctxt *ds_meta, corrupted_pages.backup_fix_ddl(ds_data, ds_meta); + DBUG_MARIABACKUP_EVENT("after_backup_fix_ddl", {}); // There is no need to stop slave thread before coping non-Innodb data when // --no-lock option is used because --no-lock option requires that no DDL or // DML to non-transaction tables can occur. diff --git a/extra/mariabackup/xtrabackup.cc b/extra/mariabackup/xtrabackup.cc index f41d9f0313f17..163d82fa807c9 100644 --- a/extra/mariabackup/xtrabackup.cc +++ b/extra/mariabackup/xtrabackup.cc @@ -1034,15 +1034,14 @@ static void backup_file_op_fail(uint32_t space_id, int type, { const char *error= ""; bool fail = false; + const std::string spacename{filename_to_spacename(name, len)}; switch(type) { case FILE_CREATE: msg("DDL tracking : create %" PRIu32 " \"%.*s\"", space_id, int(len), name); - fail = !check_if_skip_table( - filename_to_spacename(name, len).c_str()); + fail = !check_if_skip_table(spacename.c_str()); if (fail && !opt_no_lock && - check_if_fts_table( - filename_to_spacename(name, len).c_str())) { + check_if_fts_table(spacename.c_str())) { /* Ignore the FTS internal table because InnoDB does create intermediate table and their associative FTS internal table when table is being rebuilt during @@ -1061,18 +1060,25 @@ static void backup_file_op_fail(uint32_t space_id, int type, case FILE_RENAME: msg("DDL tracking : rename %" PRIu32 " \"%.*s\",\"%.*s\"", space_id, int(len), name, int(new_len), new_name); - fail = !check_if_skip_table( - filename_to_spacename(name, len).c_str()) + fail = !check_if_skip_table(spacename.c_str()) || !check_if_skip_table( filename_to_spacename(new_name, new_len).c_str()); error= "rename"; break; case FILE_DELETE: - fail = !check_if_skip_table( - filename_to_spacename(name, len).c_str()); + fail = !check_if_skip_table(spacename.c_str()); msg("DDL tracking : delete %" PRIu32 " \"%.*s\"", space_id, int(len), name); error= "delete"; + if (fail && !opt_no_lock && + check_if_fts_table(spacename.c_str())) { + /* Ignore the FTS internal table because InnoDB may + drop intermediate table and their associative FTS + internal table as a part of inplace rollback operation. + backup_set_alter_copy_lock() downgrades the + MDL_BACKUP_DDL before inplace phase of alter */ + fail = false; + } break; default: ut_ad(0); diff --git a/mysql-test/suite/mariabackup/alter_copy_race.result b/mysql-test/suite/mariabackup/alter_copy_race.result index 82202249f81c7..174ca4aa57c20 100644 --- a/mysql-test/suite/mariabackup/alter_copy_race.result +++ b/mysql-test/suite/mariabackup/alter_copy_race.result @@ -22,3 +22,21 @@ SELECT * FROM t1; i 1 DROP TABLE t1; +# +# MDEV-38041 MariaBackup fails during rollback of +# inplace FTS alter table +# +CREATE TABLE t1(f1 int, f2 char(100), fulltext(f2)) ENGINE=InnoDB; +INSERT into t1 values(1, "MariaDB"), (1, "MySQL"); +connect con2, localhost, root,,; +set lock_wait_timeout=1; +SET debug_sync='copy_data_between_tables_before_reset_backup_lock SIGNAL go WAIT_FOR after_backup_stage_block_commit'; +SET debug_sync='alter_table_after_temp_table_drop SIGNAL temp_table_dropped'; +SET debug_sync='now WAIT_FOR after_backup_stage_start';ALTER TABLE test.t1 ADD PRIMARY KEY(f1), algorithm=COPY;| +connection default; +connection con2; +ERROR 23000: Duplicate entry '1' for key 'PRIMARY' +SET debug_sync='RESET'; +disconnect con2; +connection default; +DROP TABLE t1; diff --git a/mysql-test/suite/mariabackup/alter_copy_race.test b/mysql-test/suite/mariabackup/alter_copy_race.test index 553643bf6671f..23fdf470e37c8 100644 --- a/mysql-test/suite/mariabackup/alter_copy_race.test +++ b/mysql-test/suite/mariabackup/alter_copy_race.test @@ -49,3 +49,42 @@ exec $XTRABACKUP --prepare --target-dir=$targetdir; SELECT * FROM t1; DROP TABLE t1; rmdir $targetdir; + +--echo # +--echo # MDEV-38041 MariaBackup fails during rollback of +--echo # inplace FTS alter table +--echo # + +let $targetdir=$MYSQLTEST_VARDIR/tmp/backup; + +CREATE TABLE t1(f1 int, f2 char(100), fulltext(f2)) ENGINE=InnoDB; +INSERT into t1 values(1, "MariaDB"), (1, "MySQL"); + +connect con2, localhost, root,,; +set lock_wait_timeout=1; +SET debug_sync='copy_data_between_tables_before_reset_backup_lock SIGNAL go WAIT_FOR after_backup_stage_block_commit'; +SET debug_sync='alter_table_after_temp_table_drop SIGNAL temp_table_dropped'; +DELIMITER |; +send SET debug_sync='now WAIT_FOR after_backup_stage_start';ALTER TABLE test.t1 ADD PRIMARY KEY(f1), algorithm=COPY;| +DELIMITER ;| +connection default; + +# setup mariabackup events +let backup_fix_ddl=; +let after_backup_stage_start=SET debug_sync='now SIGNAL after_backup_stage_start WAIT_FOR go'; +let after_backup_stage_block_commit=SET debug_sync='now SIGNAL after_backup_stage_block_commit'; +let after_backup_fix_ddl=SET debug_sync='now WAIT_FOR temp_table_dropped'; +let $backup_log=$MYSQLTEST_VARDIR/tmp/backup.log; +--disable_result_log +exec $XTRABACKUP --defaults-file=$MYSQLTEST_VARDIR/my.cnf --backup --target-dir=$targetdir --dbug=+d,mariabackup_events > $backup_log 2>&1; +--enable_result_log + +connection con2; +--error ER_DUP_ENTRY +reap; +SET debug_sync='RESET'; +disconnect con2; + +connection default; +DROP TABLE t1; +rmdir $targetdir;