Merge lp:~sergei.glushchenko/percona-xtrabackup/21-bug856400 into lp:percona-xtrabackup/2.1

Proposed by Sergei Glushchenko
Status: Merged
Approved by: Alexey Kopytov
Approved revision: 535
Merged at revision: 554
Proposed branch: lp:~sergei.glushchenko/percona-xtrabackup/21-bug856400
Merge into: lp:percona-xtrabackup/2.1
Diff against target: 726 lines (+378/-102)
3 files modified
innobackupex (+96/-37)
src/xtrabackup.cc (+162/-65)
test/t/bug856400.sh (+120/-0)
To merge this branch: bzr merge lp:~sergei.glushchenko/percona-xtrabackup/21-bug856400
Reviewer Review Type Date Requested Status
Alexey Kopytov (community) Approve
George Ormond Lorch III g2 Approve
Review via email: mp+152362@code.launchpad.net

Description of the change

Bug 856400
Remove dropped tables from a full backup when merging an incremental one
The problem is that between full and incremental backups such a DDL
operations as DROP TABLE and ALTER TABLE DROP PARTITION are possible.
Incremental backup doesn't contain dropped tablespaces, while full
backup still does.
Solution is to enumerate all tablespaces in datadir (which present on
filesystem) and drop those which doesn't present in fil_system directory.
This is done once incremental backup is applied to full backup and
prepared.
Minor code refactoring has been done to avoid code duplication for
enumerating files in data directory.

To post a comment you must log in.
Revision history for this message
Sergei Glushchenko (sergei.glushchenko) wrote :
Revision history for this message
George Ormond Lorch III (gl-az) wrote :
review: Needs Information (g2)
Revision history for this message
George Ormond Lorch III (gl-az) :
review: Needs Fixing (g2)
Revision history for this message
Sergei Glushchenko (sergei.glushchenko) wrote :

George's comments on 2.0 version of MP have been addressed.

http://jenkins.percona.com/view/XtraBackup/job/percona-xtrabackup-2.1-param/209/

Revision history for this message
George Ormond Lorch III (gl-az) :
review: Approve (g2)
Revision history for this message
Alexey Kopytov (akopytov) wrote :

Same comments as in the 2.0 MP.

review: Needs Fixing
Revision history for this message
Sergei Glushchenko (sergei.glushchenko) wrote :
Revision history for this message
Sergei Glushchenko (sergei.glushchenko) wrote :
535. By Sergei Glushchenko

Merge fix for lp:856400 from 2.0 series

Revision history for this message
Alexey Kopytov (akopytov) :
review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'innobackupex'
2--- innobackupex 2013-04-17 07:54:33 +0000
3+++ innobackupex 2013-04-17 12:08:29 +0000
4@@ -225,6 +225,7 @@
5 my $xtrabackup_binary_file = 'xtrabackup_binary';
6 my $xtrabackup_pid_file = 'xtrabackup_pid';
7 my %rsync_files_hash;
8+my %processed_files;
9
10 my $xb_fn_suspended_at_start = "/xtrabackup_suspended_1";
11 my $xb_fn_suspended_at_end = "/xtrabackup_suspended_2";
12@@ -234,7 +235,8 @@
13
14 my $copy_dir_src;
15 my $copy_dir_dst;
16-my $copy_dir_exclude_regexp;
17+my $cleanup_dir_dst;
18+my $process_dir_exclude_regexp;
19 my $copy_dir_overwrite;
20
21 ######################################################################
22@@ -608,7 +610,7 @@
23 sub process_file {
24 my $process_func = shift;
25
26- if (/$copy_dir_exclude_regexp/) {
27+ if (/$process_dir_exclude_regexp/) {
28 return;
29 }
30 (my $dst_path = $File::Find::name) =~ s/^$copy_dir_src/$copy_dir_dst/;
31@@ -628,6 +630,8 @@
32 }
33
34 &$process_func($File::Find::name, $dst_path);
35+ (my $rel_path = $File::Find::name) =~ s/^$copy_dir_src//;
36+ $processed_files{$rel_path} = 1;
37 }
38 }
39
40@@ -646,9 +650,30 @@
41 }
42
43 #
44+# find() callback to remove files
45+#
46+sub remove_file_callback {
47+ if (/$process_dir_exclude_regexp/) {
48+ return;
49+ }
50+ if (-d "$File::Find::name") {
51+ return;
52+ }
53+ (my $rel_path = $File::Find::name) =~ s/^$cleanup_dir_dst//;
54+ if (!($rel_path =~ m/\//)) {
55+ return;
56+ }
57+ if (! exists $processed_files{$rel_path}) {
58+ unlink($File::Find::name) or
59+ Die("Cannot remove file $File::Find::name");
60+ }
61+}
62+
63+#
64 # copy_dir_recursively subroutine does a recursive copy of a specified
65 # directory excluding files matching a specifies regexp. If $overwrite
66-# is 1, it overwrites the existing files.
67+# is 1, it overwrites the existing files. It also updates processed_files
68+# hash with the relative paths of files been copied.
69 #
70 # SYNOPSIS
71 #
72@@ -663,9 +688,10 @@
73 # Clean paths and remove trailing slashes if any
74 $copy_dir_src = File::Spec->canonpath(shift);
75 $copy_dir_dst = File::Spec->canonpath(shift);
76- $copy_dir_exclude_regexp = shift;
77+ $process_dir_exclude_regexp = shift;
78 $copy_dir_overwrite = shift;
79
80+ undef %processed_files;
81 find(\&copy_file_callback, $copy_dir_src);
82 }
83
84@@ -685,13 +711,50 @@
85 # Clean paths and remove trailing slashes if any
86 $copy_dir_src = File::Spec->canonpath(shift);
87 $copy_dir_dst = File::Spec->canonpath(shift);
88- $copy_dir_exclude_regexp = shift;
89+ $process_dir_exclude_regexp = shift;
90 $copy_dir_overwrite = shift;
91
92+ undef %processed_files;
93 find(\&move_file_callback, $copy_dir_src);
94 }
95
96 #
97+# cleanup_dir_recursively subroutine removes files from directory
98+# excluding files matching a specifies regexp and files listed in
99+# processed_files.
100+#
101+# SYNOPSIS
102+#
103+# cleanup_dir_recursively($dir, $exclude_regexp);
104+#
105+sub cleanup_dir_recursively {
106+ # Clean paths and remove trailing slashes if any
107+ $cleanup_dir_dst = File::Spec->canonpath(shift);
108+ $process_dir_exclude_regexp = shift;
109+ find(\&remove_file_callback, $cleanup_dir_dst);
110+}
111+
112+#
113+# parse_innodb_data_file_path parse innodb_data_file_path and returns
114+# it components as array of hash refs. Each hash ref has two components
115+# the one named 'path' is the data file path as specified in the
116+# innodb-data-file-path, second one named 'filename' is the data file name
117+#
118+sub parse_innodb_data_file_path {
119+ my $innodb_data_file_path = shift;
120+ my @data_file_paths = ();
121+
122+ foreach my $data_file (split(/;/, $innodb_data_file_path)) {
123+ my $data_file_path = (split(/:/,$data_file))[0];
124+ my $data_file_name = (split(/\/+/, $data_file_path))[-1];
125+ push(@data_file_paths, {path => $data_file_path,
126+ filename => $data_file_name});
127+ }
128+
129+ return @data_file_paths;
130+}
131+
132+#
133 # copy_back subroutine copies data and index files from backup directory
134 # back to their original locations.
135 #
136@@ -750,24 +813,26 @@
137
138 # make a list of all ibdata files in the backup directory and all
139 # directories in the backup directory under which there are ibdata files
140- foreach my $a (split(/;/, $orig_innodb_data_file_path)) {
141- my $path = (split(/:/,$a))[0];
142- my $filename = (split(/\/+/, $path))[-1];
143+ foreach my $c (parse_innodb_data_file_path($orig_innodb_data_file_path)) {
144
145 # check that the backup data file exists
146- if (! -e "$backup_dir/$filename") {
147- if (-e "$backup_dir/${filename}.ibz") {
148- Die "Backup data file '$backup_dir/$filename' does not exist, but "
149- . "its compressed copy '${path}.ibz' exists. Check "
150- . "that you have run '$innobackup_script --apply-log --uncompress "
151- . "...' before attempting '$innobackup_script --copy-back ...' "
152+ if (! -e "$backup_dir/$c->{filename}") {
153+ if (-e "$backup_dir/$c->{filename}.ibz") {
154+ Die "Backup data file '$backup_dir/$c->{filename}' "
155+ . "does not exist, but "
156+ . "its compressed copy '$c->{path}.ibz' exists. Check "
157+ . "that you have run "
158+ . "'$innobackup_script --apply-log --uncompress "
159+ . "...' before attempting "
160+ . "'$innobackup_script --copy-back ...' "
161 . "or '$innobackup_script --move-back ...' !";
162 } else {
163- Die "Backup data file '$backup_dir/$filename' does not exist.";
164+ Die "Backup data file '$backup_dir/$c->{filename}' "
165+ . "does not exist.";
166 }
167 }
168
169- $excluded_files .= "|\Q$filename\E";
170+ $excluded_files .= "|\Q$c->{filename}\E";
171 }
172
173 # copy files from backup dir to their original locations
174@@ -782,12 +847,10 @@
175 print STDERR "\n$prefix Starting to $operation InnoDB system tablespace\n";
176 print STDERR "$prefix in '$backup_dir'\n";
177 print STDERR "$prefix back to original InnoDB data directory '$orig_ibdata_dir'\n";
178- foreach my $a (split(/;/, $orig_innodb_data_file_path)) {
179+ foreach my $c (parse_innodb_data_file_path($orig_innodb_data_file_path)) {
180 # get the relative pathname of a data file
181- my $path = (split(/:/,$a))[0];
182- my $filename = (split(/\/+/, $path))[-1];
183- $src_name = escape_path("$backup_dir/$filename");
184- $dst_name = escape_path("$orig_ibdata_dir/$path");
185+ $src_name = escape_path("$backup_dir/$c->{filename}");
186+ $dst_name = escape_path("$orig_ibdata_dir/$c->{path}");
187 &$move_or_copy_file($src_name, $dst_name);
188 }
189
190@@ -857,6 +920,9 @@
191 $options .= " --tmpdir=$option_tmpdir";
192 }
193
194+ my $innodb_data_file_path =
195+ get_option(\%config, $option_defaults_group, 'innodb_data_file_path');
196+
197 # run ibbackup as a child process
198 $cmdline = "$option_ibbackup_binary $options";
199
200@@ -893,23 +959,16 @@
201 if ( $option_incremental_dir ) {
202 print STDERR "$prefix Starting to copy non-InnoDB files in '$option_incremental_dir'\n";
203 print STDERR "$prefix to the full backup directory '$backup_dir'\n";
204- copy_dir_recursively($option_incremental_dir, $backup_dir,
205- '^(\.\.?|backup-my\.cnf|xtrabackup_logfile|' .
206- 'xtrabackup_binary|xtrabackup_checkpoints|' .
207- '.*\.delta|.*\.meta|ib_logfile.*)$', 1);
208- # If the latest backup has no file, we need to remove the old
209- # xtrabackup_slave_info file, because it is out of date
210- # TODO: this will not be needed when bug #856400 is fixed.
211- if ( -e "$backup_dir/xtrabackup_slave_info" ) {
212- print STDERR "\n$now $prefix No updated xtrabackup_slave_info found in incremental dir, removing stale xtrabackup_slave_info file from target dir.";
213- $cmdline = "rm $backup_dir/xtrabackup_slave_info";
214- $rcode = system("$cmdline");
215- if ($rcode) {
216- # failure
217- Die "\n$prefix Failed to remove stale xtrabackup_slave_info in $backup_dir";
218- }
219-
220+ my @skip_list = ('\.\.?','backup-my\.cnf','xtrabackup_logfile',
221+ 'xtrabackup_binary','xtrabackup_checkpoints',
222+ '.*\.delta','.*\.meta','ib_logfile.*');
223+ copy_dir_recursively($option_incremental_dir, $backup_dir,
224+ '^(' . join('|', @skip_list) . ')$', 1);
225+ foreach my $c (parse_innodb_data_file_path($innodb_data_file_path)) {
226+ push(@skip_list, "\Q$c->{filename}\E");
227 }
228+ cleanup_dir_recursively($backup_dir,
229+ '^(' . join('|', @skip_list, '.*\.ibd') . ')$');
230 }
231
232 }
233
234=== modified file 'src/xtrabackup.cc'
235--- src/xtrabackup.cc 2013-04-17 07:54:33 +0000
236+++ src/xtrabackup.cc 2013-04-17 12:08:29 +0000
237@@ -121,6 +121,8 @@
238 char *xtrabackup_tables_file = NULL;
239 hash_table_t* tables_hash;
240
241+hash_table_t* inc_dir_tables_hash;
242+
243 struct xtrabackup_tables_struct{
244 char* name;
245 hash_node_t name_hash;
246@@ -2643,7 +2645,7 @@
247 }
248
249 table = static_cast<xtrabackup_tables_t *>
250- (malloc(sizeof(xtrabackup_tables_t)
251+ (ut_malloc(sizeof(xtrabackup_tables_t)
252 + strlen(name_buf) + 1));
253 memset(table, '\0', sizeof(xtrabackup_tables_t) + strlen(name_buf) + 1);
254 table->name = ((char*)table) + sizeof(xtrabackup_tables_t);
255@@ -2657,6 +2659,37 @@
256
257 static
258 void
259+xb_tables_hash_free(hash_table_t* hash)
260+{
261+ ulint i;
262+
263+ /* free the hash elements */
264+ for (i = 0; i < hash_get_n_cells(hash); i++) {
265+ xtrabackup_tables_t* table;
266+
267+ table = static_cast<xtrabackup_tables_t *>
268+ (HASH_GET_FIRST(hash, i));
269+
270+ while (table) {
271+ xtrabackup_tables_t* prev_table = table;
272+
273+ table = static_cast<xtrabackup_tables_t *>
274+ (HASH_GET_NEXT(name_hash, prev_table));
275+
276+ HASH_DELETE(xtrabackup_tables_t, name_hash, hash,
277+ ut_fold_string(prev_table->name), prev_table);
278+ ut_free(prev_table);
279+ }
280+ }
281+
282+ /* free hash */
283+ hash_table_free(hash);
284+}
285+
286+/************************************************************************
287+Destroy table filters for partial backup. */
288+static
289+void
290 xb_filters_free()
291 {
292 if (xtrabackup_tables) {
293@@ -2670,29 +2703,7 @@
294 }
295
296 if (xtrabackup_tables_file) {
297- ulint i;
298-
299- /* free the hash elements */
300- for (i = 0; i < hash_get_n_cells(tables_hash); i++) {
301- xtrabackup_tables_t* table;
302-
303- table = static_cast<xtrabackup_tables_t *>
304- (HASH_GET_FIRST(tables_hash, i));
305-
306- while (table) {
307- xtrabackup_tables_t* prev_table = table;
308-
309- table = static_cast<xtrabackup_tables_t *>
310- (HASH_GET_NEXT(name_hash, prev_table));
311-
312- HASH_DELETE(xtrabackup_tables_t, name_hash, tables_hash,
313- ut_fold_string(prev_table->name), prev_table);
314- free(prev_table);
315- }
316- }
317-
318- /* free tables_hash */
319- hash_table_free(tables_hash);
320+ xb_tables_hash_free(tables_hash);
321 }
322 }
323
324@@ -3994,12 +4005,13 @@
325 size_t real_name_len, /* out: buffer size for real_name */
326 ibool* success) /* out: indicates error. TRUE = success */
327 {
328- char dest_dir[FN_REFLEN];
329- char dest_space_name[FN_REFLEN];
330- ibool ok;
331- fil_space_t* fil_space;
332- os_file_t file = 0;
333- ulint tablespace_flags;
334+ char dest_dir[FN_REFLEN];
335+ char dest_space_name[FN_REFLEN];
336+ ibool ok;
337+ fil_space_t* fil_space;
338+ os_file_t file = 0;
339+ ulint tablespace_flags;
340+ xtrabackup_tables_t* table;
341
342 ut_a(dbname != NULL ||
343 trx_sys_sys_space(space_id) ||
344@@ -4038,6 +4050,16 @@
345 goto found;
346 }
347
348+ /* remember space name for further reference */
349+ table = static_cast<xtrabackup_tables_t *>
350+ (ut_malloc(sizeof(xtrabackup_tables_t) +
351+ strlen(dest_space_name) + 1));
352+
353+ table->name = ((char*)table) + sizeof(xtrabackup_tables_t);
354+ strcpy(table->name, dest_space_name);
355+ HASH_INSERT(xtrabackup_tables_t, name_hash, inc_dir_tables_hash,
356+ ut_fold_string(table->name), table);
357+
358 mutex_enter(&fil_system->mutex);
359 fil_space = xb_space_get_by_name(dest_space_name);
360 mutex_exit(&fil_system->mutex);
361@@ -4154,7 +4176,7 @@
362 const char* dbname, /* in: database name (ibdata: NULL) */
363 const char* filename, /* in: file name (not a path),
364 including the .delta extension */
365- my_bool check_newer __attribute__((unused)))
366+ void* /*data*/)
367 {
368 os_file_t src_file = XB_FILE_UNDEFINED;
369 os_file_t dst_file = XB_FILE_UNDEFINED;
370@@ -4347,11 +4369,61 @@
371 }
372
373 /************************************************************************
374-Applies all .delta files from incremental_dir to the full backup.
375-@return TRUE on success. */
376-static
377-ibool
378-xtrabackup_apply_deltas(my_bool check_newer)
379+Callback to handle datadir entry. Function of this type will be called
380+for each entry which matches the mask by xb_process_datadir.
381+@return should return TRUE on success */
382+typedef ibool (*handle_datadir_entry_func_t)(
383+/*=========================================*/
384+ const char* data_home_dir, /*!<in: path to datadir */
385+ const char* db_name, /*!<in: database name */
386+ const char* file_name, /*!<in: file name with suffix */
387+ void* arg); /*!<in: caller-provided data */
388+
389+/************************************************************************
390+Callback to handle datadir entry. Deletes entry if it has no matching
391+fil_space in fil_system directory.
392+@return FALSE if delete attempt was unsuccessful */
393+static
394+ibool
395+rm_if_not_found(
396+ const char* data_home_dir, /*!<in: path to datadir */
397+ const char* db_name, /*!<in: database name */
398+ const char* file_name, /*!<in: file name with suffix */
399+ void* arg __attribute__((unused)))
400+{
401+ char name[FN_REFLEN];
402+ xtrabackup_tables_t* table;
403+
404+ snprintf(name, FN_REFLEN, "%s%s/%s",
405+ xb_dict_prefix, db_name, file_name);
406+ name[strlen(name) - XB_DICT_SUFFIX_LEN] = '\0';
407+
408+ XB_HASH_SEARCH(name_hash, inc_dir_tables_hash, ut_fold_string(name),
409+ table, (void) 0,
410+ !strcmp(table->name, name));
411+
412+ if (!table) {
413+ snprintf(name, FN_REFLEN, "%s/%s/%s", data_home_dir,
414+ db_name, file_name);
415+ return os_file_delete(name);
416+ }
417+
418+ return(TRUE);
419+}
420+
421+/************************************************************************
422+Function enumerates files in datadir (provided by path) which are matched
423+by provided suffix. For each entry callback is called.
424+@return FALSE if callback for some entry returned FALSE */
425+static
426+ibool
427+xb_process_datadir(
428+ const char* path, /*!<in: datadir path */
429+ const char* suffix, /*!<in: suffix to match
430+ against */
431+ handle_datadir_entry_func_t func, /*!<in: callback */
432+ void* data) /*!<in: additional argument for
433+ callback */
434 {
435 ulint ret;
436 char dbpath[FN_REFLEN];
437@@ -4359,56 +4431,59 @@
438 os_file_dir_t dbdir;
439 os_file_stat_t dbinfo;
440 os_file_stat_t fileinfo;
441- dberr_t err = DB_SUCCESS;
442+ ulint suffix_len;
443+ dberr_t err = DB_SUCCESS;
444 static char current_dir[2];
445
446 current_dir[0] = FN_CURLIB;
447 current_dir[1] = 0;
448 srv_data_home = current_dir;
449
450+ suffix_len = strlen(suffix);
451+
452 /* datafile */
453- dbdir = os_file_opendir(xtrabackup_incremental_dir, FALSE);
454+ dbdir = os_file_opendir(path, FALSE);
455
456 if (dbdir != NULL) {
457- ret = fil_file_readdir_next_file(&err, xtrabackup_incremental_dir, dbdir,
458+ ret = fil_file_readdir_next_file(&err, path, dbdir,
459 &fileinfo);
460 while (ret == 0) {
461 if (fileinfo.type == OS_FILE_TYPE_DIR) {
462 goto next_file_item_1;
463 }
464
465- if (strlen(fileinfo.name) > 6
466- && 0 == strcmp(fileinfo.name +
467- strlen(fileinfo.name) - 6,
468- ".delta")) {
469- if (!xtrabackup_apply_delta(
470- xtrabackup_incremental_dir, NULL,
471- fileinfo.name, check_newer))
472+ if (strlen(fileinfo.name) > suffix_len
473+ && 0 == strcmp(fileinfo.name +
474+ strlen(fileinfo.name) - suffix_len,
475+ suffix)) {
476+ if (!func(
477+ path, NULL,
478+ fileinfo.name, data))
479 {
480- return FALSE;
481+ return(FALSE);
482 }
483 }
484 next_file_item_1:
485 ret = fil_file_readdir_next_file(&err,
486- xtrabackup_incremental_dir, dbdir,
487+ path, dbdir,
488 &fileinfo);
489 }
490
491 os_file_closedir(dbdir);
492 } else {
493 msg("xtrabackup: Cannot open dir %s\n",
494- xtrabackup_incremental_dir);
495+ path);
496 }
497
498 /* single table tablespaces */
499- dir = os_file_opendir(xtrabackup_incremental_dir, FALSE);
500+ dir = os_file_opendir(path, FALSE);
501
502 if (dir == NULL) {
503 msg("xtrabackup: Cannot open dir %s\n",
504- xtrabackup_incremental_dir);
505+ path);
506 }
507
508- ret = fil_file_readdir_next_file(&err, xtrabackup_incremental_dir, dir,
509+ ret = fil_file_readdir_next_file(&err, path, dir,
510 &dbinfo);
511 while (ret == 0) {
512 if (dbinfo.type == OS_FILE_TYPE_FILE
513@@ -4417,7 +4492,7 @@
514 goto next_datadir_item;
515 }
516
517- sprintf(dbpath, "%s/%s", xtrabackup_incremental_dir,
518+ sprintf(dbpath, "%s/%s", path,
519 dbinfo.name);
520 srv_normalize_path_for_win(dbpath);
521
522@@ -4434,18 +4509,19 @@
523 goto next_file_item_2;
524 }
525
526- if (strlen(fileinfo.name) > 6
527- && 0 == strcmp(fileinfo.name +
528- strlen(fileinfo.name) - 6,
529- ".delta")) {
530- /* The name ends in .delta; try opening
531+ if (strlen(fileinfo.name) > suffix_len
532+ && 0 == strcmp(fileinfo.name +
533+ strlen(fileinfo.name) -
534+ suffix_len,
535+ suffix)) {
536+ /* The name ends in suffix; process
537 the file */
538- if (!xtrabackup_apply_delta(
539- xtrabackup_incremental_dir,
540+ if (!func(
541+ path,
542 dbinfo.name,
543- fileinfo.name, check_newer))
544+ fileinfo.name, data))
545 {
546- return FALSE;
547+ return(FALSE);
548 }
549 }
550 next_file_item_2:
551@@ -4458,13 +4534,24 @@
552 }
553 next_datadir_item:
554 ret = fil_file_readdir_next_file(&err,
555- xtrabackup_incremental_dir,
556+ path,
557 dir, &dbinfo);
558 }
559
560 os_file_closedir(dir);
561
562- return TRUE;
563+ return(TRUE);
564+}
565+
566+/************************************************************************
567+Applies all .delta files from incremental_dir to the full backup.
568+@return TRUE on success. */
569+static
570+ibool
571+xtrabackup_apply_deltas()
572+{
573+ return xb_process_datadir(xtrabackup_incremental_dir, ".delta",
574+ xtrabackup_apply_delta, NULL);
575 }
576
577 static my_bool
578@@ -4657,12 +4744,22 @@
579 goto error;
580 }
581
582- if(!xtrabackup_apply_deltas(TRUE)) {
583+ inc_dir_tables_hash = hash_create(1000);
584+
585+ if(!xtrabackup_apply_deltas()) {
586 xb_data_files_close();
587+ xb_tables_hash_free(inc_dir_tables_hash);
588 goto error;
589 }
590
591 xb_data_files_close();
592+
593+ /* Cleanup datadir from tablespaces deleted between full and
594+ incremental backups */
595+
596+ xb_process_datadir("./", ".ibd", rm_if_not_found, NULL);
597+
598+ xb_tables_hash_free(inc_dir_tables_hash);
599 }
600 sync_close();
601 sync_initialized = FALSE;
602
603=== added file 'test/t/bug856400.sh'
604--- test/t/bug856400.sh 1970-01-01 00:00:00 +0000
605+++ test/t/bug856400.sh 2013-04-17 12:08:29 +0000
606@@ -0,0 +1,120 @@
607+########################################################################
608+# Bug #856400: RENAME TABLE causes incremental prepare to fail
609+########################################################################
610+
611+. inc/common.sh
612+. inc/ib_part.sh
613+
614+start_server --innodb_file_per_table
615+
616+require_partitioning
617+
618+run_cmd $MYSQL $MYSQL_ARGS test <<EOF
619+CREATE TABLE t1(a INT) ENGINE=InnoDB;
620+INSERT INTO t1 VALUES (1), (2), (3);
621+
622+CREATE TABLE t2(a INT) ENGINE=InnoDB;
623+INSERT INTO t2 VALUES (4), (5), (6);
624+
625+CREATE TABLE p (
626+ a int
627+) ENGINE=InnoDB
628+PARTITION BY RANGE (a)
629+(PARTITION p0 VALUES LESS THAN (100),
630+ PARTITION p1 VALUES LESS THAN (200),
631+ PARTITION p2 VALUES LESS THAN (300),
632+ PARTITION p3 VALUES LESS THAN (400));
633+
634+INSERT INTO p VALUES (1), (101), (201), (301);
635+
636+
637+CREATE TABLE isam_t1(a INT) ENGINE=MyISAM;
638+INSERT INTO isam_t1 VALUES (1), (2), (3);
639+
640+CREATE TABLE isam_t2(a INT) ENGINE=MyISAM;
641+INSERT INTO isam_t2 VALUES (4), (5), (6);
642+
643+CREATE TABLE isam_p (
644+ a int
645+) ENGINE=MyISAM
646+PARTITION BY RANGE (a)
647+(PARTITION p0 VALUES LESS THAN (100),
648+ PARTITION p1 VALUES LESS THAN (200),
649+ PARTITION p2 VALUES LESS THAN (300),
650+ PARTITION p3 VALUES LESS THAN (400));
651+
652+INSERT INTO isam_p VALUES (1), (101), (201), (301);
653+
654+EOF
655+
656+# Full backup
657+vlog "Creating full backup"
658+innobackupex --no-timestamp $topdir/full
659+
660+vlog "Making changes"
661+
662+run_cmd $MYSQL $MYSQL_ARGS test <<EOF
663+
664+DROP TABLE t1;
665+
666+DROP TABLE t2;
667+CREATE TABLE t2(a INT) ENGINE=InnoDB;
668+INSERT INTO t2 VALUES (40), (50), (60);
669+
670+ALTER TABLE p DROP PARTITION p0;
671+ALTER TABLE p DROP PARTITION p1;
672+ALTER TABLE p ADD PARTITION (PARTITION p4 VALUES LESS THAN (500));
673+ALTER TABLE p ADD PARTITION (PARTITION p5 VALUES LESS THAN (600));
674+
675+INSERT INTO p VALUES (401), (501);
676+
677+
678+DROP TABLE isam_t1;
679+DROP TABLE isam_t2;
680+CREATE TABLE isam_t2(a INT) ENGINE=MyISAM;
681+
682+INSERT INTO isam_t2 VALUES (40), (50), (60);
683+
684+ALTER TABLE isam_p DROP PARTITION p0;
685+ALTER TABLE isam_p DROP PARTITION p1;
686+ALTER TABLE isam_p ADD PARTITION (PARTITION p4 VALUES LESS THAN (500));
687+ALTER TABLE isam_p ADD PARTITION (PARTITION p5 VALUES LESS THAN (600));
688+
689+INSERT INTO isam_p VALUES (401), (501);
690+
691+EOF
692+
693+vlog "Creating incremental backup"
694+
695+innobackupex --incremental --no-timestamp \
696+ --incremental-basedir=$topdir/full $topdir/inc
697+
698+vlog "Preparing backup"
699+
700+innobackupex --apply-log --redo-only $topdir/full
701+vlog "Log applied to full backup"
702+
703+innobackupex --apply-log --redo-only --incremental-dir=$topdir/inc \
704+ $topdir/full
705+vlog "Delta applied to full backup"
706+
707+innobackupex --apply-log $topdir/full
708+vlog "Data prepared for restore"
709+
710+ls -al $topdir/full/test/*
711+
712+# we expect to see
713+# 5 InnoDB tablespaces
714+count=`ls $topdir/full/test/*.ibd | wc -l`
715+vlog "$count .ibd in restore, expecting 5"
716+test $count -eq 5
717+
718+# 5 MyISAM data files
719+count=`ls $topdir/full/test/*.MYD | wc -l`
720+vlog "$count .MYD in restore, expecting 5"
721+test $count -eq 5
722+
723+# and 10 tables overall
724+count=`ls $topdir/full/test/*.frm | wc -l`
725+vlog "$count .frm in restore, expecting 4"
726+test $count -eq 4

Subscribers

People subscribed via source and target branches