Skip to content

Commit 97b97af

Browse files
MDEV-36304 InnoDB: Missing FILE_CREATE, FILE_DELETE or FILE_MODIFY error during mariabackup --prepare
Problem: ======= - During --prepare of partial backup, if InnoDB encounters the redo log for the excluded tablespace then InnoDB stores the space id in dirty tablespace list during recovery, anticipates that it may encounter FILE_* redo log records in the future. Even though we encounter FILE_* record for the partial excluded tablespace then we fail to replace the name in dirty tablespace list. This lead to missing of FILE_* redo log records error. Fix: === srv_prepare_partial_backup: Variable for the server to indicate whether the redo log has been applied on partial backup xtrabackup_read_backup_info_file(): Reads the mariabackup_info file from target directory and sets srv_prepare_partial_backup value based on partial information exist in file. fil_name_process(): Rename the file name from "" to name encountered during FILE_* records during prepare on partial backup directory
1 parent 02893e8 commit 97b97af

File tree

6 files changed

+123
-1
lines changed

6 files changed

+123
-1
lines changed

extra/mariabackup/xtrabackup.cc

+30
Original file line numberDiff line numberDiff line change
@@ -2694,6 +2694,35 @@ static bool innodb_init()
26942694

26952695
/* ================= common ================= */
26962696

2697+
/** Read the backup_info file during prepare to know whether
2698+
it is working on partial backup target directory */
2699+
static
2700+
void xtrabackup_read_backup_info_file(const char *dir,
2701+
const char *name) noexcept
2702+
{
2703+
char filename[FN_REFLEN];
2704+
snprintf(filename, sizeof(filename), "%s/%s", dir, name);
2705+
FILE *fp= fopen(filename, "r");
2706+
char key[8], value;
2707+
if (!fp)
2708+
{
2709+
msg("Error: cannot open %s", filename);
2710+
return;
2711+
}
2712+
2713+
while (!feof(fp))
2714+
{
2715+
if (fscanf(fp, "%7s = %c\n", key, &value) == 2)
2716+
if (strcmp(key, "partial") == 0)
2717+
{
2718+
if (value == 'Y')
2719+
srv_prepare_partial_backup= true;
2720+
break;
2721+
}
2722+
}
2723+
fclose(fp);
2724+
}
2725+
26972726
/***********************************************************************
26982727
Read backup meta info.
26992728
@return TRUE on success, FALSE on failure. */
@@ -6796,6 +6825,7 @@ static bool xtrabackup_prepare_func(char** argv)
67966825
return(false);
67976826
}
67986827

6828+
xtrabackup_read_backup_info_file(xtrabackup_target_dir, MB_INFO);
67996829
if (!strcmp(metadata_type, "full-backuped")) {
68006830
if (xtrabackup_incremental) {
68016831
msg("error: applying incremental backup "
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
CREATE TABLE t1(i INT) ENGINE INNODB;
2+
CREATE TABLE t2(i INT) ENGINE INNODB;
3+
INSERT INTO t1 VALUES(1);
4+
INSERT INTO t2 VALUES(2);
5+
set global innodb_log_checkpoint_now = 1;
6+
INSERT INTO t1 select * from seq_1_to_1024;
7+
INSERT INTO t2 select * from seq_1_to_1024;
8+
# restart
9+
# xtrabackup backup
10+
# xtrabackup prepare
11+
t1.cfg
12+
ALTER TABLE t1 DISCARD TABLESPACE;
13+
ALTER TABLE t1 IMPORT TABLESPACE;
14+
SELECT * FROM t1;
15+
DROP TABLE t1, t2;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
--source include/have_innodb.inc
2+
--source include/have_sequence.inc
3+
--source include/have_debug.inc
4+
--source include/not_embedded.inc
5+
6+
CREATE TABLE t1(i INT) ENGINE INNODB;
7+
CREATE TABLE t2(i INT) ENGINE INNODB;
8+
9+
INSERT INTO t1 VALUES(1);
10+
INSERT INTO t2 VALUES(2);
11+
12+
let $targetdir=$MYSQLTEST_VARDIR/tmp/backup;
13+
let $backup_log=$MYSQLTEST_VARDIR/tmp/backup.log;
14+
let $prepare_log=$MYSQLTEST_VARDIR/tmp/prepare.log;
15+
set global innodb_log_checkpoint_now = 1;
16+
INSERT INTO t1 select * from seq_1_to_1024;
17+
INSERT INTO t2 select * from seq_1_to_1024;
18+
--source include/restart_mysqld.inc
19+
echo # xtrabackup backup;
20+
exec $XTRABACKUP --defaults-file=$MYSQLTEST_VARDIR/my.cnf --dbug=+d,use_old_checkpoint --skip-innodb-log-checkpoint-now --backup "--tables=test.*1" --target-dir=$targetdir --parallel=10 > $backup_log 2>&1;
21+
22+
echo # xtrabackup prepare;
23+
--disable_result_log
24+
exec $XTRABACKUP --prepare --export --target-dir=$targetdir --dbug=+d,partial_backup_test > $prepare_log 2>&1;
25+
26+
list_files $targetdir/test *.cfg;
27+
28+
let $MYSQLD_DATADIR= `select @@datadir`;
29+
ALTER TABLE t1 DISCARD TABLESPACE;
30+
copy_file $targetdir/test/t1.ibd $MYSQLD_DATADIR/test/t1.ibd;
31+
copy_file $targetdir/test/t1.cfg $MYSQLD_DATADIR/test/t1.cfg;
32+
ALTER TABLE t1 IMPORT TABLESPACE;
33+
SELECT * FROM t1;
34+
DROP TABLE t1, t2;
35+
remove_file $backup_log;
36+
remove_file $prepare_log;
37+
rmdir $targetdir;

storage/innobase/include/srv0srv.h

+2
Original file line numberDiff line numberDiff line change
@@ -329,6 +329,8 @@ extern enum srv_operation_mode srv_operation;
329329
/** whether this is the server's first start after mariabackup --prepare */
330330
extern bool srv_start_after_restore;
331331

332+
extern bool srv_prepare_partial_backup;
333+
332334
extern my_bool srv_print_innodb_monitor;
333335
extern my_bool srv_print_innodb_lock_monitor;
334336
extern ibool srv_print_verbose_log;

storage/innobase/log/log0recv.cc

+36-1
Original file line numberDiff line numberDiff line change
@@ -1175,7 +1175,6 @@ static void fil_name_process(const char *name, ulint len, uint32_t space_id,
11751175
|| f.name != fname.name) {
11761176
reload:
11771177
fil_space_t* space;
1178-
11791178
/* Check if the tablespace file exists and contains
11801179
the space_id. If not, ignore the file after displaying
11811180
a note. Abort if there are multiple files with the
@@ -1232,6 +1231,18 @@ static void fil_name_process(const char *name, ulint len, uint32_t space_id,
12321231
break;
12331232
}
12341233

1234+
/* In case of prepare on partial backup,
1235+
InnoDB can't find some tablespace on target
1236+
directory. If InnoDB encounters redo log
1237+
for the tablespace before FILE_* record then
1238+
InnoDB should rename the file name in
1239+
recv_spaces from "" to name which encountered
1240+
during FILE_* record */
1241+
if (srv_prepare_partial_backup &&
1242+
strcmp(fname.name.c_str(), "") == 0) {
1243+
f.name= fname.name;
1244+
}
1245+
12351246
if (srv_force_recovery
12361247
|| srv_operation == SRV_OPERATION_RESTORE) {
12371248
/* Without innodb_force_recovery,
@@ -1249,6 +1260,17 @@ static void fil_name_process(const char *name, ulint len, uint32_t space_id,
12491260
int(fname.name.size()),
12501261
fname.name.data(), space_id);
12511262
}
1263+
1264+
DBUG_EXECUTE_IF("partial_backup_test",
1265+
char *exist=
1266+
strstr(const_cast<char*>(name),
1267+
"t2.ibd");
1268+
static uint32_t n_exist= 0;
1269+
if (exist && n_exist == 0)
1270+
{
1271+
n_exist++;
1272+
recv_spaces.erase(space_id);
1273+
});
12521274
break;
12531275

12541276
case FIL_LOAD_DEFER:
@@ -1751,13 +1773,26 @@ dberr_t recv_sys_t::find_checkpoint()
17511773
continue;
17521774
}
17531775

1776+
DBUG_EXECUTE_IF("use_old_checkpoint",
1777+
if (log_sys.next_checkpoint_lsn > 0) {
1778+
if (checkpoint_lsn > log_sys.next_checkpoint_lsn)
1779+
goto skip_lsn;
1780+
else goto assign_lsn;
1781+
}
1782+
);
17541783
if (checkpoint_lsn >= log_sys.next_checkpoint_lsn)
17551784
{
1785+
#ifndef DBUG_OFF
1786+
assign_lsn:
1787+
#endif /* !DBUG_OFF */
17561788
log_sys.next_checkpoint_lsn= checkpoint_lsn;
17571789
log_sys.next_checkpoint_no= field == log_t::CHECKPOINT_1;
17581790
lsn= end_lsn;
17591791
}
17601792
}
1793+
#ifndef DBUG_OFF
1794+
skip_lsn:
1795+
#endif /* !DBUG_OFF */
17611796
if (!log_sys.next_checkpoint_lsn)
17621797
goto got_no_checkpoint;
17631798
if (!memcmp(creator, "Backup ", 7))

storage/innobase/srv/srv0srv.cc

+3
Original file line numberDiff line numberDiff line change
@@ -314,6 +314,9 @@ enum srv_operation_mode srv_operation;
314314
/** whether this is the server's first start after mariabackup --prepare */
315315
bool srv_start_after_restore;
316316

317+
/** Whether mariabackup --prepare working on partial backup target */
318+
bool srv_prepare_partial_backup;
319+
317320
/* Set the following to 0 if you want InnoDB to write messages on
318321
stderr on startup/shutdown. Not enabled on the embedded server. */
319322
ibool srv_print_verbose_log;

0 commit comments

Comments
 (0)