summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexander Barkov <bar@mariadb.com>2022-11-09 16:41:19 +0400
committerAlexander Barkov <bar@mariadb.com>2023-01-19 17:18:06 +0400
commit0ddbec40fbba8ce818489c82a1b679a0b33aa50e (patch)
tree350910d7af7989f9af1268ee37c589aedfa802b4
parent489b556947087f7606224d6fc09f302eabef14c8 (diff)
downloadmariadb-git-0ddbec40fbba8ce818489c82a1b679a0b33aa50e.tar.gz
MDEV-23335 MariaBackup Incremental Does Not Reflect Dropped/Created Databases
-rw-r--r--extra/mariabackup/backup_copy.cc49
-rw-r--r--mysql-test/suite/mariabackup/incremental_drop_db.result30
-rw-r--r--mysql-test/suite/mariabackup/incremental_drop_db.test68
3 files changed, 146 insertions, 1 deletions
diff --git a/extra/mariabackup/backup_copy.cc b/extra/mariabackup/backup_copy.cc
index 23ade2a46be..57dfdbc7ad4 100644
--- a/extra/mariabackup/backup_copy.cc
+++ b/extra/mariabackup/backup_copy.cc
@@ -57,6 +57,9 @@ Street, Fifth Floor, Boston, MA 02110-1335 USA
#include "backup_copy.h"
#include "backup_mysql.h"
#include <btr0btr.h>
+#ifdef _WIN32
+#include <direct.h> /* rmdir */
+#endif
#define ROCKSDB_BACKUP_DIR "#rocksdb"
@@ -1623,7 +1626,49 @@ bool backup_finish()
return(true);
}
-bool
+
+/*
+ Drop all empty database directories in the base backup
+ that do not exists in the icremental backup.
+
+ This effectively re-plays all DROP DATABASE statements happened
+ in between base backup and incremental backup creation time.
+
+ Note, only checking if base_dir/db/ is empty is not enough,
+ because inc_dir/db/db.opt might have been dropped for some reasons,
+ which may also result into empty base_dir/db/.
+
+ Only the fact that at the same time:
+ - base_dir/db/ exists
+ - inc_dir/db/ does not exist
+ means that DROP DATABASE happened.
+*/
+static void
+ibx_incremental_drop_databases(const char *base_dir,
+ const char *inc_dir)
+{
+ datadir_node_t node;
+ datadir_node_init(&node);
+ datadir_iter_t *it = datadir_iter_new(base_dir);
+
+ while (datadir_iter_next(it, &node)) {
+ if (node.is_empty_dir) {
+ char path[FN_REFLEN];
+ snprintf(path, sizeof(path), "%s/%s",
+ inc_dir, node.filepath_rel);
+ if (!directory_exists(path, false)) {
+ msg("Removing %s", node.filepath);
+ rmdir(node.filepath);
+ }
+ }
+
+ }
+ datadir_iter_free(it);
+ datadir_node_free(&node);
+}
+
+
+static bool
ibx_copy_incremental_over_full()
{
const char *ext_list[] = {"frm", "isl", "MYD", "MYI", "MAD", "MAI",
@@ -1706,6 +1751,8 @@ ibx_copy_incremental_over_full()
}
copy_or_move_dir(path, ROCKSDB_BACKUP_DIR, true, true);
}
+ ibx_incremental_drop_databases(xtrabackup_target_dir,
+ xtrabackup_incremental_dir);
}
diff --git a/mysql-test/suite/mariabackup/incremental_drop_db.result b/mysql-test/suite/mariabackup/incremental_drop_db.result
new file mode 100644
index 00000000000..027f99974fe
--- /dev/null
+++ b/mysql-test/suite/mariabackup/incremental_drop_db.result
@@ -0,0 +1,30 @@
+call mtr.add_suppression("InnoDB: New log files created");
+#
+# Start of 10.3 tests
+#
+#
+# MDEV-23335 MariaBackup Incremental Does Not Reflect Dropped/Created Databases
+#
+CREATE DATABASE db1;
+CREATE DATABASE db2;
+CREATE TABLE db1.t1 (a INT) ENGINE=MyISAM;
+CREATE TABLE db1.t2 (a INT) ENGINE=InnoDB;
+# Create base backup
+DROP DATABASE db1;
+# Create incremental backup
+# Remove incremental_dir/db2/db.opt file to make incremental_dir/db2/ empty
+# Prepare base backup, apply incremental one
+# shutdown server
+# remove datadir
+# xtrabackup move back
+# restart server
+# Expect no 'db1' in the output, because it was really dropped.
+# Expect 'db2' in the ouput, because it was not dropped!
+# (its incremental directory was emptied only)
+SHOW DATABASES LIKE 'db%';
+Database (db%)
+db2
+DROP DATABASE db2;
+#
+# End of 10.3 tests
+#
diff --git a/mysql-test/suite/mariabackup/incremental_drop_db.test b/mysql-test/suite/mariabackup/incremental_drop_db.test
new file mode 100644
index 00000000000..de270435e9d
--- /dev/null
+++ b/mysql-test/suite/mariabackup/incremental_drop_db.test
@@ -0,0 +1,68 @@
+--source include/have_innodb.inc
+call mtr.add_suppression("InnoDB: New log files created");
+
+--echo #
+--echo # Start of 10.3 tests
+--echo #
+
+--echo #
+--echo # MDEV-23335 MariaBackup Incremental Does Not Reflect Dropped/Created Databases
+--echo #
+
+--let $datadir=`SELECT @@datadir`
+--let $basedir=$MYSQLTEST_VARDIR/tmp/backup
+--let $incremental_dir=$MYSQLTEST_VARDIR/tmp/backup_inc1
+
+# Create two databases:
+# - db1 is dropped normally below
+# - db2 is used to cover a corner case: its db.opt file is removed
+
+# Incremental backup contains:
+# - no directory for db1
+# - an empty directory for db2 (after we remove db2/db.opt)
+
+
+CREATE DATABASE db1;
+CREATE DATABASE db2;
+
+# Add some tables to db1
+CREATE TABLE db1.t1 (a INT) ENGINE=MyISAM;
+CREATE TABLE db1.t2 (a INT) ENGINE=InnoDB;
+
+--echo # Create base backup
+--disable_result_log
+--exec $XTRABACKUP --defaults-file=$MYSQLTEST_VARDIR/my.cnf --backup --target-dir=$basedir
+--enable_result_log
+
+DROP DATABASE db1;
+
+--echo # Create incremental backup
+--exec $XTRABACKUP --defaults-file=$MYSQLTEST_VARDIR/my.cnf --backup --target-dir=$incremental_dir --incremental-basedir=$basedir
+
+--echo # Remove incremental_dir/db2/db.opt file to make incremental_dir/db2/ empty
+--remove_file $incremental_dir/db2/db.opt
+
+
+--echo # Prepare base backup, apply incremental one
+--disable_result_log
+--exec $XTRABACKUP --prepare --target-dir=$basedir
+--exec $XTRABACKUP --prepare --target-dir=$basedir --incremental-dir=$incremental_dir
+--enable_result_log
+
+--let $targetdir=$basedir
+--source include/restart_and_restore.inc
+--enable_result_log
+
+--echo # Expect no 'db1' in the output, because it was really dropped.
+--echo # Expect 'db2' in the ouput, because it was not dropped!
+--echo # (its incremental directory was emptied only)
+
+SHOW DATABASES LIKE 'db%';
+DROP DATABASE db2;
+
+--rmdir $basedir
+--rmdir $incremental_dir
+
+--echo #
+--echo # End of 10.3 tests
+--echo #