Skip to content

Commit 6b2da93

Browse files
committed
MDEV-17192 Backup with -no-lock should fail, if DDL is detected at the end of backup
1 parent 28f08d3 commit 6b2da93

File tree

3 files changed

+81
-5
lines changed

3 files changed

+81
-5
lines changed

extra/mariabackup/xtrabackup.cc

Lines changed: 65 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -588,7 +588,7 @@ std::string filename_to_spacename(const byte *filename, size_t len)
588588
@param[in] len length of name, in bytes
589589
@param[in] new_name new file name (NULL if not rename)
590590
@param[in] new_len length of new_name, in bytes (0 if NULL) */
591-
void backup_file_op(ulint space_id, const byte* flags,
591+
static void backup_file_op(ulint space_id, const byte* flags,
592592
const byte* name, ulint len,
593593
const byte* new_name, ulint new_len)
594594
{
@@ -616,19 +616,71 @@ void backup_file_op(ulint space_id, const byte* flags,
616616
}
617617

618618

619+
/*
620+
This callback is called if DDL operation is detected,
621+
at the end of backup
622+
623+
Normally, DDL operations are blocked due to FTWRL,
624+
but in rare cases of --no-lock, they are not.
625+
626+
We will abort backup in this case.
627+
*/
628+
static void backup_file_op_fail(ulint space_id, const byte* flags,
629+
const byte* name, ulint len,
630+
const byte* new_name, ulint new_len)
631+
{
632+
ut_a(opt_no_lock);
633+
bool fail;
634+
if (flags) {
635+
msg("DDL tracking : create %zu \"%.*s\": %x\n",
636+
space_id, int(len), name, mach_read_from_4(flags));
637+
std::string spacename = filename_to_spacename(name, len);
638+
fail = !check_if_skip_table(spacename.c_str());
639+
}
640+
else if (new_name) {
641+
msg("DDL tracking : rename %zu \"%.*s\",\"%.*s\"\n",
642+
space_id, int(len), name, int(new_len), new_name);
643+
std::string spacename = filename_to_spacename(name, len);
644+
std::string new_spacename = filename_to_spacename(new_name, new_len);
645+
fail = !check_if_skip_table(spacename.c_str()) || !check_if_skip_table(new_spacename.c_str());
646+
}
647+
else {
648+
std::string spacename = filename_to_spacename(name, len);
649+
fail = !check_if_skip_table(spacename.c_str());
650+
msg("DDL tracking : delete %zu \"%.*s\"\n", space_id, int(len), name);
651+
}
652+
if (fail) {
653+
msg("ERROR : DDL operation detected in the late phase of backup."
654+
"Backup is inconsistent. Remove --no-lock option to fix.\n");
655+
exit(EXIT_FAILURE);
656+
}
657+
}
658+
659+
619660
/** Callback whenever MLOG_INDEX_LOAD happens.
620661
@param[in] space_id space id to check */
621662
static void backup_optimized_ddl_op(ulint space_id)
622663
{
623-
// TODO : handle incremental
624-
if (xtrabackup_incremental)
625-
return;
626-
627664
pthread_mutex_lock(&backup_mutex);
628665
ddl_tracker.optimized_ddl.insert(space_id);
629666
pthread_mutex_unlock(&backup_mutex);
630667
}
631668

669+
/*
670+
Optimized DDL callback at the end of backup that
671+
run with --no-lock. Usually aborts the backup.
672+
*/
673+
static void backup_optimized_ddl_op_fail(ulint space_id) {
674+
ut_a(opt_no_lock);
675+
msg("DDL tracking : optimized DDL on space %zu\n");
676+
if (ddl_tracker.tables_in_backup.find(space_id) != ddl_tracker.tables_in_backup.end()) {
677+
msg("ERROR : Optimized DDL operation detected in the late phase of backup."
678+
"Backup is inconsistent. Remove --no-lock option to fix.\n");
679+
exit(EXIT_FAILURE);
680+
}
681+
}
682+
683+
632684
/** Callback whenever MLOG_TRUNCATE happens. */
633685
static void backup_truncate_fail()
634686
{
@@ -4383,6 +4435,14 @@ void backup_fix_ddl(void)
43834435
std::set<std::string> dropped_tables;
43844436
std::map<std::string, std::string> renamed_tables;
43854437

4438+
/* Disable further DDL on backed up tables (only needed for --no-lock).*/
4439+
pthread_mutex_lock(&backup_mutex);
4440+
log_file_op = backup_file_op_fail;
4441+
log_optimized_ddl_op = backup_optimized_ddl_op_fail;
4442+
pthread_mutex_unlock(&backup_mutex);
4443+
4444+
DBUG_MARIABACKUP_EVENT("backup_fix_ddl",0);
4445+
43864446
for (space_id_to_name_t::iterator iter = ddl_tracker.tables_in_backup.begin();
43874447
iter != ddl_tracker.tables_in_backup.end();
43884448
iter++) {
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
CREATE TABLE t1(i int) ENGINE=INNODB;
2+
# xtrabackup backup
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
--source include/have_debug.inc
2+
let $targetdir=$MYSQLTEST_VARDIR/tmp/backup;
3+
mkdir $targetdir;
4+
5+
CREATE TABLE t1(i int) ENGINE=INNODB;
6+
7+
# this will table and populate it, after backup has list of tables to be copied
8+
--let backup_fix_ddl=BEGIN NOT ATOMIC DROP TABLE test.t1;DO SLEEP(10000); END
9+
echo # xtrabackup backup;
10+
--disable_result_log
11+
error 1;
12+
exec $XTRABACKUP --defaults-file=$MYSQLTEST_VARDIR/my.cnf --backup --target-dir=$targetdir --no-lock --dbug=+d,mariabackup_events;
13+
--enable_result_log
14+
rmdir $targetdir;

0 commit comments

Comments
 (0)