Skip to content

Commit

Permalink
PXB-3227 Dropped table is still in the backup
Browse files Browse the repository at this point in the history
How to reproduce :
1 . Create table t1.ibd before the backup
2. Start backup with --lock-ddl=REDUCED
3. Pause at debug_sync_point("xtrabackup_suspend_at_start");
4. RENAME t1.ibd -> t2.ibd
5. DROP t2.ibd
6. Run prepare
7. we end up with t1.ibd in the backup which should have been dropped

PXB-3229 Can't create/write to file 't2.ibd.del' (OS errno 17 - File exists)
How to reproduce :
1.Create tables t1.ibd t3.ibd before the backup
2.Start backup with --lock-ddl=REDUCED
3.Pause atdebug_sync_point("xtrabackup_suspend_at_start");
4.RENAME t1.ibd -> t2.ibd
5.DROP t2.ibd
6.RENAME t3.ibd -> t2.ibd
7.DROP t2.ibd
8.Can't create/write to file 't2.ibd.del' (OS errno 17 - File exists)

Fix:
if dropped table was renamed from another table and original_table was created before backup started and have been copied then we should create `.del` file for original_table and skip creating `.del` file for renamed_table
  • Loading branch information
aybek committed Feb 1, 2024
1 parent 840cf50 commit e03db06
Show file tree
Hide file tree
Showing 3 changed files with 136 additions and 5 deletions.
39 changes: 34 additions & 5 deletions storage/innobase/xtrabackup/src/ddl_tracker.cc
Original file line number Diff line number Diff line change
Expand Up @@ -195,11 +195,19 @@ void ddl_tracker_t::handle_ddl_operations() {

/* Some tables might get to the new list if the DDL happen in between
* redo_mgr.start and xb_load_tablespaces. This causes we ending up with two
* tablespaces with the same spaceID. Remove them from new tables */
* tablespaces with the same spaceID. Remove them from new tables
*
* Rename DDL can happen in between redo_mgr.start and xb_load_tablespaces
* as well. In this case we should erase rename DDL cause we already scanned
* the table with new name */
for (auto &table : tables_in_backup) {
if (new_tables.find(table.first) != new_tables.end()) {
new_tables.erase(table.first);
}
if (renames.find(table.first) != renames.end() &&
renames[table.first].second == table.second) {
renames.erase(table.first);
}
}

/* recopy_tables will be handled as follow:
Expand All @@ -223,15 +231,36 @@ void ddl_tracker_t::handle_ddl_operations() {
if (check_if_skip_table(table.second.c_str())) {
continue;
}
/* Remove from rename */
renames.erase(table.first);

/* Remove from new tables and skip drop*/
/* Remove from new tables and skip drop */
if (new_tables.find(table.first) != new_tables.end()) {
new_tables.erase(table.first);

/* Remove from rename */
renames.erase(table.first);
continue;
}

/* If table_space_id does not exist in new_tables nor in tables_in_backup
then this drop ddl happened between redo_mgr.start and xb_tablespace_load.
We skip drop.
*/
if (new_tables.find(table.first) == new_tables.end() &&
tables_in_backup.find(table.first) == tables_in_backup.end()) {
continue;
}
backup_file_printf((table.second + ".del").c_str(), "%s", "");

if (renames.find(table.first) != renames.end()) {
/* If original table was there before backup start and have been copied
then we should delete it */
backup_file_printf((renames[table.first].first + ".del").c_str(), "%s",
"");

/* Remove from rename */
renames.erase(table.first);
} else {
backup_file_printf((table.second + ".del").c_str(), "%s", "");
}
}

for (auto &table : renames) {
Expand Down
3 changes: 3 additions & 0 deletions storage/innobase/xtrabackup/src/xtrabackup.cc
Original file line number Diff line number Diff line change
Expand Up @@ -4254,6 +4254,9 @@ void xtrabackup_backup_func(void) {

Tablespace_map::instance().scan(mysql_connection);

debug_sync_point(
"xtrabackup_suspend_between_redo_mgr_start_and_xb_load_tablespaces");

/* Populate fil_system with tablespaces to copy */
dberr_t err = xb_load_tablespaces();
if (err != DB_SUCCESS) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
#########################################################################################
# PXB-3227: Rename table and then drop table, make sure that original table was deleted
#########################################################################################

. inc/common.sh

require_debug_pxb_version
start_server

$MYSQL $MYSQL_ARGS -Ns -e "CREATE TABLE test.original_table (id INT PRIMARY KEY AUTO_INCREMENT); INSERT INTO test.original_table VALUES(1);" test
innodb_wait_for_flush_all

xtrabackup --backup --target-dir=$topdir/backup \
--debug-sync="xtrabackup_suspend_at_start" --lock-ddl=REDUCED \
2> >( tee $topdir/backup.log)&

job_pid=$!
pid_file=$topdir/backup/xtrabackup_debug_sync
wait_for_xb_to_suspend $pid_file
xb_pid=`cat $pid_file`
echo "backup pid is $job_pid"

# Rename table and generate redo
$MYSQL $MYSQL_ARGS -Ns -e "RENAME TABLE test.original_table TO test.renamed_table; INSERT INTO test.renamed_table VALUES (2);" test
# Drop table
$MYSQL $MYSQL_ARGS -Ns -e "DROP TABLE test.renamed_table;" test

# Resume the xtrabackup process
vlog "Resuming xtrabackup"
kill -SIGCONT $xb_pid
run_cmd wait $job_pid

if ! egrep -q "Done: Writing file $topdir/backup/test/original_table.ibd.del" $topdir/backup.log ; then
die "xtrabackup did not create .del file for original_table"
fi

xtrabackup --prepare --target-dir=$topdir/backup
record_db_state test
stop_server
rm -rf $mysql_datadir/*
xtrabackup --copy-back --target-dir=$topdir/backup
start_server
verify_db_state test

if [ -f $mysql_datadir/test/original_table.ibd ] ; then
die 'dropped original_table.ibd file has been copied to the datadir'
fi

stop_server
rm -rf $topdir/backup

#########################################################################################################
# PXB-3229: Make sure backup does not fail with `File exists` error trying to create .del file twice
#########################################################################################################

start_server

$MYSQL $MYSQL_ARGS -Ns -e "CREATE TABLE test.t1 (id INT PRIMARY KEY AUTO_INCREMENT); INSERT INTO test.t1 VALUES(1);" test
$MYSQL $MYSQL_ARGS -Ns -e "CREATE TABLE test.t2 (id INT PRIMARY KEY AUTO_INCREMENT); INSERT INTO test.t2 VALUES(1);" test
innodb_wait_for_flush_all

xtrabackup --backup --target-dir=$topdir/backup \
--debug-sync="xtrabackup_suspend_at_start" --lock-ddl=REDUCED \
2> >( tee $topdir/backup.log)&

job_pid=$!
pid_file=$topdir/backup/xtrabackup_debug_sync
wait_for_xb_to_suspend $pid_file
xb_pid=`cat $pid_file`
echo "backup pid is $job_pid"

# Rename table and generate redo
$MYSQL $MYSQL_ARGS -Ns -e "RENAME TABLE test.t1 TO test.t3; INSERT INTO test.t3 VALUES (2);" test
# Drop table
$MYSQL $MYSQL_ARGS -Ns -e "DROP TABLE test.t3;" test
# Rename table and generate redo
$MYSQL $MYSQL_ARGS -Ns -e "RENAME TABLE test.t2 TO test.t3; INSERT INTO test.t3 VALUES (2);" test
# Drop table
$MYSQL $MYSQL_ARGS -Ns -e "DROP TABLE test.t3;" test

# Resume the xtrabackup process
vlog "Resuming xtrabackup"
kill -SIGCONT $xb_pid
run_cmd wait $job_pid

xtrabackup --prepare --target-dir=$topdir/backup
record_db_state test
stop_server
rm -rf $mysql_datadir/*
xtrabackup --copy-back --target-dir=$topdir/backup
start_server
verify_db_state test
stop_server
rm -rf $mysql_datadir $topdir/backup





0 comments on commit e03db06

Please sign in to comment.