Merge lp:~sergei.glushchenko/percona-xtrabackup/20-bug856400 into lp:percona-xtrabackup/2.0
- 20-bug856400
- Merge into 2.0
Status: | Merged |
---|---|
Approved by: | Alexey Kopytov |
Approved revision: | no longer in the source branch. |
Merged at revision: | 537 |
Proposed branch: | lp:~sergei.glushchenko/percona-xtrabackup/20-bug856400 |
Merge into: | lp:percona-xtrabackup/2.0 |
Diff against target: |
717 lines (+373/-100) 3 files modified
innobackupex (+96/-37) src/xtrabackup.cc (+157/-63) test/t/bug856400.sh (+120/-0) |
To merge this branch: | bzr merge lp:~sergei.glushchenko/percona-xtrabackup/20-bug856400 |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Alexey Kopytov (community) | Approve | ||
George Ormond Lorch III (community) | g2 | Approve | |
Review via email: mp+152361@code.launchpad.net |
Commit message
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.
Sergei Glushchenko (sergei.glushchenko) wrote : | # |
Sergei Glushchenko (sergei.glushchenko) wrote : | # |
George Ormond Lorch III (gl-az) wrote : | # |
Introduced/moved code that had compilation warnings and should be addressed:
xtrabackup.cc: In function ‘ulint rm_if_not_
xtrabackup.cc:6383: warning: unused variable ‘space’ [-Wunused-variable]
Other than the warning, the fix seems reasonable, I like the use of the fn pointer to try to keep the code reasonably factored.
One minor thing is that around diff line 346, if xtrabackup_
Sergei Glushchenko (sergei.glushchenko) wrote : | # |
Issue with warning has been fixed as long as memory deallocation.
http://
George Ormond Lorch III (gl-az) wrote : | # |
Nice work.
Alexey Kopytov (akopytov) wrote : | # |
As discussed on IRC, this also has to handle non-InnoDB files (frm, MyISAM, metainfo, etc.)
Sergei Glushchenko (sergei.glushchenko) wrote : | # |
innobackupex part implemented
http://
Alexey Kopytov (akopytov) wrote : | # |
Sergei,
Some comments and questions:
- conflict in xtrabackup.cc
- typo in the comments for cleanup_
- wrong bug reference in the test case comments
- there's no need for "\/+" in the following code:
:+ (my $rel_path = $File::Find::name) =~ s/^$copy_
- can you clarify the purpose of the code in lines 50-52?
- error handling for unlink() would be nice
- did you take the comment in lines 125-128 into account?
- a few lines are longer than 80 chars, try:
: bzr diff -c-1 | grep -0 '^+' | expand | awk 'length > 80'
or better yet, try to use a good text editor that can be configured
to highlight such lines
- the check_newer argument is not used. does it really make sense to
add some _new_ code to support it? Wouldn't it be better to get rid
of it?
- in the test, do we really have to restart the server between full
and incremental backup, or it's just a copy-paste from another test?
Sergei Glushchenko (sergei.glushchenko) wrote : | # |
Hi Alexey,
* changes
- rebased on latest trunk
- typo in cleanup_
- bug reference in the test case comments fixed
- added error handling for unlink
- removed restart of server in testcase
- parse innodb_
system tablespace
* other things
- there was a need for "\/+"
because otherwise lines 50-52 wont give expected result
- lines 50-52 were needed to restrict copying of contents of
top level of datadir; now it is not needed as I start using
value of innodb_
system tablespace
- I will never configure my text editor to highlight long lines, thanks;
this is not a good place to discuss text editors and their settings
- I think to have a possibility to pass user argument to callback
is always a good idea, no matter whether this needed at the
moment or not; but I changed the code to get rid of check_newer
* Jenkins
- http://
Thanks,
Sergei
Alexey Kopytov (akopytov) wrote : | # |
Sergei,
- I was referring to the check_newer argument of
xtrabackup_
unused. It's good that you changed the argument to
xtrabackup_
confusing this way. Please also remove the argument of
xtrabackup_
something like "xtrabackup_
that TRUE is there just in case.
- I don't understand this code around parsing
innodb_
files from cleaning up. You loop through paths returned by
parse_
single one and add them to skip_list. Don't you want to add
filenames instead of paths? And what's the goal of removing
multiple slashes again?
- I also see you replaced "strcpy(
with "sprintf(
you don't really need sprintf() there.
Sergei Glushchenko (sergei.glushchenko) wrote : | # |
Alexey,
Indeed, I forgot to cleanup things like xtrabackup_
What if I have MyISAM table named test_table and innodb_
s/strcpy/sprintf/ is really an accident, sorry :)
Sergei Glushchenko (sergei.glushchenko) wrote : | # |
However for this specific case using just a filename from innodb_
If our tablespace is named say xtrabackup_
The reason why I started to think in that side was just a discomfort when I write a code that decide whether to remove file or not by using just it's name instead of fully qualified path.
Tree is updated, jenkins run is started, but supposedly it will be finished by tomorrow
http://
Alexey Kopytov (akopytov) : | # |
Preview Diff
1 | === modified file 'innobackupex' | |||
2 | --- innobackupex 2013-04-03 07:04:25 +0000 | |||
3 | +++ innobackupex 2013-04-17 12:03:25 +0000 | |||
4 | @@ -225,10 +225,12 @@ | |||
5 | 225 | my $xtrabackup_binary_file = 'xtrabackup_binary'; | 225 | my $xtrabackup_binary_file = 'xtrabackup_binary'; |
6 | 226 | my $xtrabackup_pid_file = 'xtrabackup_pid'; | 226 | my $xtrabackup_pid_file = 'xtrabackup_pid'; |
7 | 227 | my %rsync_files_hash; | 227 | my %rsync_files_hash; |
8 | 228 | my %processed_files; | ||
9 | 228 | 229 | ||
10 | 229 | my $copy_dir_src; | 230 | my $copy_dir_src; |
11 | 230 | my $copy_dir_dst; | 231 | my $copy_dir_dst; |
13 | 231 | my $copy_dir_exclude_regexp; | 232 | my $cleanup_dir_dst; |
14 | 233 | my $process_dir_exclude_regexp; | ||
15 | 232 | my $copy_dir_overwrite; | 234 | my $copy_dir_overwrite; |
16 | 233 | 235 | ||
17 | 234 | ###################################################################### | 236 | ###################################################################### |
18 | @@ -619,7 +621,7 @@ | |||
19 | 619 | sub process_file { | 621 | sub process_file { |
20 | 620 | my $process_func = shift; | 622 | my $process_func = shift; |
21 | 621 | 623 | ||
23 | 622 | if (/$copy_dir_exclude_regexp/) { | 624 | if (/$process_dir_exclude_regexp/) { |
24 | 623 | return; | 625 | return; |
25 | 624 | } | 626 | } |
26 | 625 | (my $dst_path = $File::Find::name) =~ s/^$copy_dir_src/$copy_dir_dst/; | 627 | (my $dst_path = $File::Find::name) =~ s/^$copy_dir_src/$copy_dir_dst/; |
27 | @@ -639,6 +641,8 @@ | |||
28 | 639 | } | 641 | } |
29 | 640 | 642 | ||
30 | 641 | &$process_func($File::Find::name, $dst_path); | 643 | &$process_func($File::Find::name, $dst_path); |
31 | 644 | (my $rel_path = $File::Find::name) =~ s/^$copy_dir_src//; | ||
32 | 645 | $processed_files{$rel_path} = 1; | ||
33 | 642 | } | 646 | } |
34 | 643 | } | 647 | } |
35 | 644 | 648 | ||
36 | @@ -657,9 +661,30 @@ | |||
37 | 657 | } | 661 | } |
38 | 658 | 662 | ||
39 | 659 | # | 663 | # |
40 | 664 | # find() callback to remove files | ||
41 | 665 | # | ||
42 | 666 | sub remove_file_callback { | ||
43 | 667 | if (/$process_dir_exclude_regexp/) { | ||
44 | 668 | return; | ||
45 | 669 | } | ||
46 | 670 | if (-d "$File::Find::name") { | ||
47 | 671 | return; | ||
48 | 672 | } | ||
49 | 673 | (my $rel_path = $File::Find::name) =~ s/^$cleanup_dir_dst//; | ||
50 | 674 | if (!($rel_path =~ m/\//)) { | ||
51 | 675 | return; | ||
52 | 676 | } | ||
53 | 677 | if (! exists $processed_files{$rel_path}) { | ||
54 | 678 | unlink($File::Find::name) or | ||
55 | 679 | Die("Cannot remove file $File::Find::name"); | ||
56 | 680 | } | ||
57 | 681 | } | ||
58 | 682 | |||
59 | 683 | # | ||
60 | 660 | # copy_dir_recursively subroutine does a recursive copy of a specified | 684 | # copy_dir_recursively subroutine does a recursive copy of a specified |
61 | 661 | # directory excluding files matching a specifies regexp. If $overwrite | 685 | # directory excluding files matching a specifies regexp. If $overwrite |
63 | 662 | # is 1, it overwrites the existing files. | 686 | # is 1, it overwrites the existing files. It also updates processed_files |
64 | 687 | # hash with the relative paths of files been copied. | ||
65 | 663 | # | 688 | # |
66 | 664 | # SYNOPSIS | 689 | # SYNOPSIS |
67 | 665 | # | 690 | # |
68 | @@ -674,9 +699,10 @@ | |||
69 | 674 | # Clean paths and remove trailing slashes if any | 699 | # Clean paths and remove trailing slashes if any |
70 | 675 | $copy_dir_src = File::Spec->canonpath(shift); | 700 | $copy_dir_src = File::Spec->canonpath(shift); |
71 | 676 | $copy_dir_dst = File::Spec->canonpath(shift); | 701 | $copy_dir_dst = File::Spec->canonpath(shift); |
73 | 677 | $copy_dir_exclude_regexp = shift; | 702 | $process_dir_exclude_regexp = shift; |
74 | 678 | $copy_dir_overwrite = shift; | 703 | $copy_dir_overwrite = shift; |
75 | 679 | 704 | ||
76 | 705 | undef %processed_files; | ||
77 | 680 | find(\©_file_callback, $copy_dir_src); | 706 | find(\©_file_callback, $copy_dir_src); |
78 | 681 | } | 707 | } |
79 | 682 | 708 | ||
80 | @@ -696,13 +722,50 @@ | |||
81 | 696 | # Clean paths and remove trailing slashes if any | 722 | # Clean paths and remove trailing slashes if any |
82 | 697 | $copy_dir_src = File::Spec->canonpath(shift); | 723 | $copy_dir_src = File::Spec->canonpath(shift); |
83 | 698 | $copy_dir_dst = File::Spec->canonpath(shift); | 724 | $copy_dir_dst = File::Spec->canonpath(shift); |
85 | 699 | $copy_dir_exclude_regexp = shift; | 725 | $process_dir_exclude_regexp = shift; |
86 | 700 | $copy_dir_overwrite = shift; | 726 | $copy_dir_overwrite = shift; |
87 | 701 | 727 | ||
88 | 728 | undef %processed_files; | ||
89 | 702 | find(\&move_file_callback, $copy_dir_src); | 729 | find(\&move_file_callback, $copy_dir_src); |
90 | 703 | } | 730 | } |
91 | 704 | 731 | ||
92 | 705 | # | 732 | # |
93 | 733 | # cleanup_dir_recursively subroutine removes files from directory | ||
94 | 734 | # excluding files matching a specifies regexp and files listed in | ||
95 | 735 | # processed_files. | ||
96 | 736 | # | ||
97 | 737 | # SYNOPSIS | ||
98 | 738 | # | ||
99 | 739 | # cleanup_dir_recursively($dir, $exclude_regexp); | ||
100 | 740 | # | ||
101 | 741 | sub cleanup_dir_recursively { | ||
102 | 742 | # Clean paths and remove trailing slashes if any | ||
103 | 743 | $cleanup_dir_dst = File::Spec->canonpath(shift); | ||
104 | 744 | $process_dir_exclude_regexp = shift; | ||
105 | 745 | find(\&remove_file_callback, $cleanup_dir_dst); | ||
106 | 746 | } | ||
107 | 747 | |||
108 | 748 | # | ||
109 | 749 | # parse_innodb_data_file_path parse innodb_data_file_path and returns | ||
110 | 750 | # it components as array of hash refs. Each hash ref has two components | ||
111 | 751 | # the one named 'path' is the data file path as specified in the | ||
112 | 752 | # innodb-data-file-path, second one named 'filename' is the data file name | ||
113 | 753 | # | ||
114 | 754 | sub parse_innodb_data_file_path { | ||
115 | 755 | my $innodb_data_file_path = shift; | ||
116 | 756 | my @data_file_paths = (); | ||
117 | 757 | |||
118 | 758 | foreach my $data_file (split(/;/, $innodb_data_file_path)) { | ||
119 | 759 | my $data_file_path = (split(/:/,$data_file))[0]; | ||
120 | 760 | my $data_file_name = (split(/\/+/, $data_file_path))[-1]; | ||
121 | 761 | push(@data_file_paths, {path => $data_file_path, | ||
122 | 762 | filename => $data_file_name}); | ||
123 | 763 | } | ||
124 | 764 | |||
125 | 765 | return @data_file_paths; | ||
126 | 766 | } | ||
127 | 767 | |||
128 | 768 | # | ||
129 | 706 | # copy_back subroutine copies data and index files from backup directory | 769 | # copy_back subroutine copies data and index files from backup directory |
130 | 707 | # back to their original locations. | 770 | # back to their original locations. |
131 | 708 | # | 771 | # |
132 | @@ -760,24 +823,26 @@ | |||
133 | 760 | 823 | ||
134 | 761 | # make a list of all ibdata files in the backup directory and all | 824 | # make a list of all ibdata files in the backup directory and all |
135 | 762 | # directories in the backup directory under which there are ibdata files | 825 | # directories in the backup directory under which there are ibdata files |
139 | 763 | foreach my $a (split(/;/, $orig_innodb_data_file_path)) { | 826 | foreach my $c (parse_innodb_data_file_path($orig_innodb_data_file_path)) { |
137 | 764 | my $path = (split(/:/,$a))[0]; | ||
138 | 765 | my $filename = (split(/\/+/, $path))[-1]; | ||
140 | 766 | 827 | ||
141 | 767 | # check that the backup data file exists | 828 | # check that the backup data file exists |
148 | 768 | if (! -e "$backup_dir/$filename") { | 829 | if (! -e "$backup_dir/$c->{filename}") { |
149 | 769 | if (-e "$backup_dir/${filename}.ibz") { | 830 | if (-e "$backup_dir/$c->{filename}.ibz") { |
150 | 770 | Die "Backup data file '$backup_dir/$filename' does not exist, but " | 831 | Die "Backup data file '$backup_dir/$c->{filename}' " |
151 | 771 | . "its compressed copy '${path}.ibz' exists. Check " | 832 | . "does not exist, but " |
152 | 772 | . "that you have run '$innobackup_script --apply-log --uncompress " | 833 | . "its compressed copy '$c->{path}.ibz' exists. Check " |
153 | 773 | . "...' before attempting '$innobackup_script --copy-back ...' " | 834 | . "that you have run " |
154 | 835 | . "'$innobackup_script --apply-log --uncompress " | ||
155 | 836 | . "...' before attempting " | ||
156 | 837 | . "'$innobackup_script --copy-back ...' " | ||
157 | 774 | . "or '$innobackup_script --move-back ...' !"; | 838 | . "or '$innobackup_script --move-back ...' !"; |
158 | 775 | } else { | 839 | } else { |
160 | 776 | Die "Backup data file '$backup_dir/$filename' does not exist."; | 840 | Die "Backup data file '$backup_dir/$c->{filename}' " |
161 | 841 | . "does not exist."; | ||
162 | 777 | } | 842 | } |
163 | 778 | } | 843 | } |
164 | 779 | 844 | ||
166 | 780 | $excluded_files .= "|\Q$filename\E"; | 845 | $excluded_files .= "|\Q$c->{filename}\E"; |
167 | 781 | } | 846 | } |
168 | 782 | 847 | ||
169 | 783 | # copy files from backup dir to their original locations | 848 | # copy files from backup dir to their original locations |
170 | @@ -792,12 +857,10 @@ | |||
171 | 792 | print STDERR "\n$prefix Starting to $operation InnoDB system tablespace\n"; | 857 | print STDERR "\n$prefix Starting to $operation InnoDB system tablespace\n"; |
172 | 793 | print STDERR "$prefix in '$backup_dir'\n"; | 858 | print STDERR "$prefix in '$backup_dir'\n"; |
173 | 794 | print STDERR "$prefix back to original InnoDB data directory '$orig_ibdata_dir'\n"; | 859 | print STDERR "$prefix back to original InnoDB data directory '$orig_ibdata_dir'\n"; |
175 | 795 | foreach my $a (split(/;/, $orig_innodb_data_file_path)) { | 860 | foreach my $c (parse_innodb_data_file_path($orig_innodb_data_file_path)) { |
176 | 796 | # get the relative pathname of a data file | 861 | # get the relative pathname of a data file |
181 | 797 | my $path = (split(/:/,$a))[0]; | 862 | $src_name = escape_path("$backup_dir/$c->{filename}"); |
182 | 798 | my $filename = (split(/\/+/, $path))[-1]; | 863 | $dst_name = escape_path("$orig_ibdata_dir/$c->{path}"); |
179 | 799 | $src_name = escape_path("$backup_dir/$filename"); | ||
180 | 800 | $dst_name = escape_path("$orig_ibdata_dir/$path"); | ||
183 | 801 | &$move_or_copy_file($src_name, $dst_name); | 864 | &$move_or_copy_file($src_name, $dst_name); |
184 | 802 | } | 865 | } |
185 | 803 | 866 | ||
186 | @@ -866,6 +929,9 @@ | |||
187 | 866 | $options .= " --tmpdir=$option_tmpdir"; | 929 | $options .= " --tmpdir=$option_tmpdir"; |
188 | 867 | } | 930 | } |
189 | 868 | 931 | ||
190 | 932 | my $innodb_data_file_path = | ||
191 | 933 | get_option(\%config, $option_defaults_group, 'innodb_data_file_path'); | ||
192 | 934 | |||
193 | 869 | # run ibbackup as a child process | 935 | # run ibbackup as a child process |
194 | 870 | $cmdline = "$option_ibbackup_binary $options"; | 936 | $cmdline = "$option_ibbackup_binary $options"; |
195 | 871 | $now = current_time(); | 937 | $now = current_time(); |
196 | @@ -894,23 +960,16 @@ | |||
197 | 894 | if ( $option_incremental_dir ) { | 960 | if ( $option_incremental_dir ) { |
198 | 895 | print STDERR "$prefix Starting to copy non-InnoDB files in '$option_incremental_dir'\n"; | 961 | print STDERR "$prefix Starting to copy non-InnoDB files in '$option_incremental_dir'\n"; |
199 | 896 | print STDERR "$prefix to the full backup directory '$backup_dir'\n"; | 962 | print STDERR "$prefix to the full backup directory '$backup_dir'\n"; |
216 | 897 | copy_dir_recursively($option_incremental_dir, $backup_dir, | 963 | my @skip_list = ('\.\.?','backup-my\.cnf','xtrabackup_logfile', |
217 | 898 | '^(\.\.?|backup-my\.cnf|xtrabackup_logfile|' . | 964 | 'xtrabackup_binary','xtrabackup_checkpoints', |
218 | 899 | 'xtrabackup_binary|xtrabackup_checkpoints|' . | 965 | '.*\.delta','.*\.meta','ib_logfile.*'); |
219 | 900 | '.*\.delta|.*\.meta|ib_logfile.*)$', 1); | 966 | copy_dir_recursively($option_incremental_dir, $backup_dir, |
220 | 901 | # If the latest backup has no file, we need to remove the old | 967 | '^(' . join('|', @skip_list) . ')$', 1); |
221 | 902 | # xtrabackup_slave_info file, because it is out of date | 968 | foreach my $c (parse_innodb_data_file_path($innodb_data_file_path)) { |
222 | 903 | # TODO: this will not be needed when bug #856400 is fixed. | 969 | push(@skip_list, "\Q$c->{filename}\E"); |
207 | 904 | if ( -e "$backup_dir/xtrabackup_slave_info" ) { | ||
208 | 905 | print STDERR "\n$now $prefix No updated xtrabackup_slave_info found in incremental dir, removing stale xtrabackup_slave_info file from target dir."; | ||
209 | 906 | $cmdline = "rm $backup_dir/xtrabackup_slave_info"; | ||
210 | 907 | $rcode = system("$cmdline"); | ||
211 | 908 | if ($rcode) { | ||
212 | 909 | # failure | ||
213 | 910 | Die "\n$prefix Failed to remove stale xtrabackup_slave_info in $backup_dir"; | ||
214 | 911 | } | ||
215 | 912 | |||
223 | 913 | } | 970 | } |
224 | 971 | cleanup_dir_recursively($backup_dir, | ||
225 | 972 | '^(' . join('|', @skip_list, '.*\.ibd') . ')$'); | ||
226 | 914 | } | 973 | } |
227 | 915 | 974 | ||
228 | 916 | } | 975 | } |
229 | 917 | 976 | ||
230 | === modified file 'src/xtrabackup.cc' | |||
231 | --- src/xtrabackup.cc 2013-04-03 22:53:49 +0000 | |||
232 | +++ src/xtrabackup.cc 2013-04-17 12:03:25 +0000 | |||
233 | @@ -1334,6 +1334,8 @@ | |||
234 | 1334 | char *xtrabackup_tables_file = NULL; | 1334 | char *xtrabackup_tables_file = NULL; |
235 | 1335 | hash_table_t* tables_hash; | 1335 | hash_table_t* tables_hash; |
236 | 1336 | 1336 | ||
237 | 1337 | hash_table_t* inc_dir_tables_hash; | ||
238 | 1338 | |||
239 | 1337 | struct xtrabackup_tables_struct{ | 1339 | struct xtrabackup_tables_struct{ |
240 | 1338 | char* name; | 1340 | char* name; |
241 | 1339 | hash_node_t name_hash; | 1341 | hash_node_t name_hash; |
242 | @@ -5006,7 +5008,7 @@ | |||
243 | 5006 | } | 5008 | } |
244 | 5007 | 5009 | ||
245 | 5008 | table = static_cast<xtrabackup_tables_t *> | 5010 | table = static_cast<xtrabackup_tables_t *> |
247 | 5009 | (malloc(sizeof(xtrabackup_tables_t) | 5011 | (ut_malloc(sizeof(xtrabackup_tables_t) |
248 | 5010 | + strlen(name_buf) + 1)); | 5012 | + strlen(name_buf) + 1)); |
249 | 5011 | memset(table, '\0', sizeof(xtrabackup_tables_t) + strlen(name_buf) + 1); | 5013 | memset(table, '\0', sizeof(xtrabackup_tables_t) + strlen(name_buf) + 1); |
250 | 5012 | table->name = ((char*)table) + sizeof(xtrabackup_tables_t); | 5014 | table->name = ((char*)table) + sizeof(xtrabackup_tables_t); |
251 | @@ -5018,6 +5020,34 @@ | |||
252 | 5018 | } | 5020 | } |
253 | 5019 | } | 5021 | } |
254 | 5020 | 5022 | ||
255 | 5023 | static | ||
256 | 5024 | void | ||
257 | 5025 | xb_tables_hash_free(hash_table_t* hash) | ||
258 | 5026 | { | ||
259 | 5027 | ulint i; | ||
260 | 5028 | |||
261 | 5029 | /* free the hash elements */ | ||
262 | 5030 | for (i = 0; i < hash_get_n_cells(hash); i++) { | ||
263 | 5031 | xtrabackup_tables_t* table; | ||
264 | 5032 | |||
265 | 5033 | table = static_cast<xtrabackup_tables_t *> | ||
266 | 5034 | (HASH_GET_FIRST(hash, i)); | ||
267 | 5035 | |||
268 | 5036 | while (table) { | ||
269 | 5037 | xtrabackup_tables_t* prev_table = table; | ||
270 | 5038 | |||
271 | 5039 | table = static_cast<xtrabackup_tables_t *> | ||
272 | 5040 | (HASH_GET_NEXT(name_hash, prev_table)); | ||
273 | 5041 | |||
274 | 5042 | HASH_DELETE(xtrabackup_tables_t, name_hash, hash, | ||
275 | 5043 | ut_fold_string(prev_table->name), prev_table); | ||
276 | 5044 | ut_free(prev_table); | ||
277 | 5045 | } | ||
278 | 5046 | } | ||
279 | 5047 | |||
280 | 5048 | /* free hash */ | ||
281 | 5049 | hash_table_free(hash); | ||
282 | 5050 | } | ||
283 | 5021 | 5051 | ||
284 | 5022 | /************************************************************************ | 5052 | /************************************************************************ |
285 | 5023 | Destroy table filters for partial backup. */ | 5053 | Destroy table filters for partial backup. */ |
286 | @@ -5028,29 +5058,7 @@ | |||
287 | 5028 | { | 5058 | { |
288 | 5029 | 5059 | ||
289 | 5030 | if (xtrabackup_tables_file) { | 5060 | if (xtrabackup_tables_file) { |
313 | 5031 | ulint i; | 5061 | xb_tables_hash_free(tables_hash); |
291 | 5032 | |||
292 | 5033 | /* free the hash elements */ | ||
293 | 5034 | for (i = 0; i < hash_get_n_cells(tables_hash); i++) { | ||
294 | 5035 | xtrabackup_tables_t* table; | ||
295 | 5036 | |||
296 | 5037 | table = static_cast<xtrabackup_tables_t *> | ||
297 | 5038 | (HASH_GET_FIRST(tables_hash, i)); | ||
298 | 5039 | |||
299 | 5040 | while (table) { | ||
300 | 5041 | xtrabackup_tables_t* prev_table = table; | ||
301 | 5042 | |||
302 | 5043 | table = static_cast<xtrabackup_tables_t *> | ||
303 | 5044 | (HASH_GET_NEXT(name_hash, prev_table)); | ||
304 | 5045 | |||
305 | 5046 | HASH_DELETE(xtrabackup_tables_t, name_hash, tables_hash, | ||
306 | 5047 | ut_fold_string(prev_table->name), prev_table); | ||
307 | 5048 | free(prev_table); | ||
308 | 5049 | } | ||
309 | 5050 | } | ||
310 | 5051 | |||
311 | 5052 | /* free tables_hash */ | ||
312 | 5053 | hash_table_free(tables_hash); | ||
314 | 5054 | } | 5062 | } |
315 | 5055 | 5063 | ||
316 | 5056 | } | 5064 | } |
317 | @@ -6625,12 +6633,13 @@ | |||
318 | 6625 | size_t real_name_len, /* out: buffer size for real_name */ | 6633 | size_t real_name_len, /* out: buffer size for real_name */ |
319 | 6626 | ibool* success) /* out: indicates error. TRUE = success */ | 6634 | ibool* success) /* out: indicates error. TRUE = success */ |
320 | 6627 | { | 6635 | { |
327 | 6628 | char dest_dir[FN_REFLEN]; | 6636 | char dest_dir[FN_REFLEN]; |
328 | 6629 | char dest_space_name[FN_REFLEN]; | 6637 | char dest_space_name[FN_REFLEN]; |
329 | 6630 | ibool ok; | 6638 | ibool ok; |
330 | 6631 | fil_space_t* fil_space; | 6639 | fil_space_t* fil_space; |
331 | 6632 | os_file_t file = 0; | 6640 | os_file_t file = 0; |
332 | 6633 | ulint tablespace_flags; | 6641 | ulint tablespace_flags; |
333 | 6642 | xtrabackup_tables_t* table; | ||
334 | 6634 | 6643 | ||
335 | 6635 | ut_a(dbname != NULL || | 6644 | ut_a(dbname != NULL || |
336 | 6636 | trx_sys_sys_space(space_id) || | 6645 | trx_sys_sys_space(space_id) || |
337 | @@ -6669,6 +6678,16 @@ | |||
338 | 6669 | goto found; | 6678 | goto found; |
339 | 6670 | } | 6679 | } |
340 | 6671 | 6680 | ||
341 | 6681 | /* remember space name for further reference */ | ||
342 | 6682 | table = static_cast<xtrabackup_tables_t *> | ||
343 | 6683 | (ut_malloc(sizeof(xtrabackup_tables_t) + | ||
344 | 6684 | strlen(dest_space_name) + 1)); | ||
345 | 6685 | |||
346 | 6686 | table->name = ((char*)table) + sizeof(xtrabackup_tables_t); | ||
347 | 6687 | strcpy(table->name, dest_space_name); | ||
348 | 6688 | HASH_INSERT(xtrabackup_tables_t, name_hash, inc_dir_tables_hash, | ||
349 | 6689 | ut_fold_string(table->name), table); | ||
350 | 6690 | |||
351 | 6672 | mutex_enter(&fil_system->mutex); | 6691 | mutex_enter(&fil_system->mutex); |
352 | 6673 | fil_space = xb_space_get_by_name(dest_space_name); | 6692 | fil_space = xb_space_get_by_name(dest_space_name); |
353 | 6674 | mutex_exit(&fil_system->mutex); | 6693 | mutex_exit(&fil_system->mutex); |
354 | @@ -6792,7 +6811,7 @@ | |||
355 | 6792 | const char* dbname, /* in: database name (ibdata: NULL) */ | 6811 | const char* dbname, /* in: database name (ibdata: NULL) */ |
356 | 6793 | const char* filename, /* in: file name (not a path), | 6812 | const char* filename, /* in: file name (not a path), |
357 | 6794 | including the .delta extension */ | 6813 | including the .delta extension */ |
359 | 6795 | my_bool check_newer __attribute__((unused))) | 6814 | void* /*data*/) |
360 | 6796 | { | 6815 | { |
361 | 6797 | os_file_t src_file = XB_FILE_UNDEFINED; | 6816 | os_file_t src_file = XB_FILE_UNDEFINED; |
362 | 6798 | os_file_t dst_file = XB_FILE_UNDEFINED; | 6817 | os_file_t dst_file = XB_FILE_UNDEFINED; |
363 | @@ -6989,11 +7008,61 @@ | |||
364 | 6989 | } | 7008 | } |
365 | 6990 | 7009 | ||
366 | 6991 | /************************************************************************ | 7010 | /************************************************************************ |
372 | 6992 | Applies all .delta files from incremental_dir to the full backup. | 7011 | Callback to handle datadir entry. Function of this type will be called |
373 | 6993 | @return TRUE on success. */ | 7012 | for each entry which matches the mask by xb_process_datadir. |
374 | 6994 | static | 7013 | @return should return TRUE on success */ |
375 | 6995 | ibool | 7014 | typedef ibool (*handle_datadir_entry_func_t)( |
376 | 6996 | xtrabackup_apply_deltas(my_bool check_newer) | 7015 | /*=========================================*/ |
377 | 7016 | const char* data_home_dir, /*!<in: path to datadir */ | ||
378 | 7017 | const char* db_name, /*!<in: database name */ | ||
379 | 7018 | const char* file_name, /*!<in: file name with suffix */ | ||
380 | 7019 | void* arg); /*!<in: caller-provided data */ | ||
381 | 7020 | |||
382 | 7021 | /************************************************************************ | ||
383 | 7022 | Callback to handle datadir entry. Deletes entry if it has no matching | ||
384 | 7023 | fil_space in fil_system directory. | ||
385 | 7024 | @return FALSE if delete attempt was unsuccessful */ | ||
386 | 7025 | static | ||
387 | 7026 | ibool | ||
388 | 7027 | rm_if_not_found( | ||
389 | 7028 | const char* data_home_dir, /*!<in: path to datadir */ | ||
390 | 7029 | const char* db_name, /*!<in: database name */ | ||
391 | 7030 | const char* file_name, /*!<in: file name with suffix */ | ||
392 | 7031 | void* arg __attribute__((unused))) | ||
393 | 7032 | { | ||
394 | 7033 | char name[FN_REFLEN]; | ||
395 | 7034 | xtrabackup_tables_t* table; | ||
396 | 7035 | |||
397 | 7036 | snprintf(name, FN_REFLEN, "%s%s/%s", | ||
398 | 7037 | xb_dict_prefix, db_name, file_name); | ||
399 | 7038 | name[strlen(name) - XB_DICT_SUFFIX_LEN] = '\0'; | ||
400 | 7039 | |||
401 | 7040 | XB_HASH_SEARCH(name_hash, inc_dir_tables_hash, ut_fold_string(name), | ||
402 | 7041 | table, (void) 0, | ||
403 | 7042 | !strcmp(table->name, name)); | ||
404 | 7043 | |||
405 | 7044 | if (!table) { | ||
406 | 7045 | snprintf(name, FN_REFLEN, "%s/%s/%s", data_home_dir, | ||
407 | 7046 | db_name, file_name); | ||
408 | 7047 | return os_file_delete(name); | ||
409 | 7048 | } | ||
410 | 7049 | |||
411 | 7050 | return(TRUE); | ||
412 | 7051 | } | ||
413 | 7052 | |||
414 | 7053 | /************************************************************************ | ||
415 | 7054 | Function enumerates files in datadir (provided by path) which are matched | ||
416 | 7055 | by provided suffix. For each entry callback is called. | ||
417 | 7056 | @return FALSE if callback for some entry returned FALSE */ | ||
418 | 7057 | static | ||
419 | 7058 | ibool | ||
420 | 7059 | xb_process_datadir( | ||
421 | 7060 | const char* path, /*!<in: datadir path */ | ||
422 | 7061 | const char* suffix, /*!<in: suffix to match | ||
423 | 7062 | against */ | ||
424 | 7063 | handle_datadir_entry_func_t func, /*!<in: callback */ | ||
425 | 7064 | void* data) /*!<in: additional argument for | ||
426 | 7065 | callback */ | ||
427 | 6997 | { | 7066 | { |
428 | 6998 | ulint ret; | 7067 | ulint ret; |
429 | 6999 | char dbpath[FN_REFLEN]; | 7068 | char dbpath[FN_REFLEN]; |
430 | @@ -7001,56 +7070,59 @@ | |||
431 | 7001 | os_file_dir_t dbdir; | 7070 | os_file_dir_t dbdir; |
432 | 7002 | os_file_stat_t dbinfo; | 7071 | os_file_stat_t dbinfo; |
433 | 7003 | os_file_stat_t fileinfo; | 7072 | os_file_stat_t fileinfo; |
435 | 7004 | dberr_t err = DB_SUCCESS; | 7073 | ulint suffix_len; |
436 | 7074 | dberr_t err = DB_SUCCESS; | ||
437 | 7005 | static char current_dir[2]; | 7075 | static char current_dir[2]; |
438 | 7006 | 7076 | ||
439 | 7007 | current_dir[0] = FN_CURLIB; | 7077 | current_dir[0] = FN_CURLIB; |
440 | 7008 | current_dir[1] = 0; | 7078 | current_dir[1] = 0; |
441 | 7009 | srv_data_home = current_dir; | 7079 | srv_data_home = current_dir; |
442 | 7010 | 7080 | ||
443 | 7081 | suffix_len = strlen(suffix); | ||
444 | 7082 | |||
445 | 7011 | /* datafile */ | 7083 | /* datafile */ |
447 | 7012 | dbdir = os_file_opendir(xtrabackup_incremental_dir, FALSE); | 7084 | dbdir = os_file_opendir(path, FALSE); |
448 | 7013 | 7085 | ||
449 | 7014 | if (dbdir != NULL) { | 7086 | if (dbdir != NULL) { |
451 | 7015 | ret = fil_file_readdir_next_file(&err, xtrabackup_incremental_dir, dbdir, | 7087 | ret = fil_file_readdir_next_file(&err, path, dbdir, |
452 | 7016 | &fileinfo); | 7088 | &fileinfo); |
453 | 7017 | while (ret == 0) { | 7089 | while (ret == 0) { |
454 | 7018 | if (fileinfo.type == OS_FILE_TYPE_DIR) { | 7090 | if (fileinfo.type == OS_FILE_TYPE_DIR) { |
455 | 7019 | goto next_file_item_1; | 7091 | goto next_file_item_1; |
456 | 7020 | } | 7092 | } |
457 | 7021 | 7093 | ||
459 | 7022 | if (strlen(fileinfo.name) > 6 | 7094 | if (strlen(fileinfo.name) > suffix_len |
460 | 7023 | && 0 == strcmp(fileinfo.name + | 7095 | && 0 == strcmp(fileinfo.name + |
466 | 7024 | strlen(fileinfo.name) - 6, | 7096 | strlen(fileinfo.name) - suffix_len, |
467 | 7025 | ".delta")) { | 7097 | suffix)) { |
468 | 7026 | if (!xtrabackup_apply_delta( | 7098 | if (!func( |
469 | 7027 | xtrabackup_incremental_dir, NULL, | 7099 | path, NULL, |
470 | 7028 | fileinfo.name, check_newer)) | 7100 | fileinfo.name, data)) |
471 | 7029 | { | 7101 | { |
473 | 7030 | return FALSE; | 7102 | return(FALSE); |
474 | 7031 | } | 7103 | } |
475 | 7032 | } | 7104 | } |
476 | 7033 | next_file_item_1: | 7105 | next_file_item_1: |
477 | 7034 | ret = fil_file_readdir_next_file(&err, | 7106 | ret = fil_file_readdir_next_file(&err, |
479 | 7035 | xtrabackup_incremental_dir, dbdir, | 7107 | path, dbdir, |
480 | 7036 | &fileinfo); | 7108 | &fileinfo); |
481 | 7037 | } | 7109 | } |
482 | 7038 | 7110 | ||
483 | 7039 | os_file_closedir(dbdir); | 7111 | os_file_closedir(dbdir); |
484 | 7040 | } else { | 7112 | } else { |
485 | 7041 | msg("xtrabackup: Cannot open dir %s\n", | 7113 | msg("xtrabackup: Cannot open dir %s\n", |
487 | 7042 | xtrabackup_incremental_dir); | 7114 | path); |
488 | 7043 | } | 7115 | } |
489 | 7044 | 7116 | ||
490 | 7045 | /* single table tablespaces */ | 7117 | /* single table tablespaces */ |
492 | 7046 | dir = os_file_opendir(xtrabackup_incremental_dir, FALSE); | 7118 | dir = os_file_opendir(path, FALSE); |
493 | 7047 | 7119 | ||
494 | 7048 | if (dir == NULL) { | 7120 | if (dir == NULL) { |
495 | 7049 | msg("xtrabackup: Cannot open dir %s\n", | 7121 | msg("xtrabackup: Cannot open dir %s\n", |
497 | 7050 | xtrabackup_incremental_dir); | 7122 | path); |
498 | 7051 | } | 7123 | } |
499 | 7052 | 7124 | ||
501 | 7053 | ret = fil_file_readdir_next_file(&err, xtrabackup_incremental_dir, dir, | 7125 | ret = fil_file_readdir_next_file(&err, path, dir, |
502 | 7054 | &dbinfo); | 7126 | &dbinfo); |
503 | 7055 | while (ret == 0) { | 7127 | while (ret == 0) { |
504 | 7056 | if (dbinfo.type == OS_FILE_TYPE_FILE | 7128 | if (dbinfo.type == OS_FILE_TYPE_FILE |
505 | @@ -7059,7 +7131,7 @@ | |||
506 | 7059 | goto next_datadir_item; | 7131 | goto next_datadir_item; |
507 | 7060 | } | 7132 | } |
508 | 7061 | 7133 | ||
510 | 7062 | sprintf(dbpath, "%s/%s", xtrabackup_incremental_dir, | 7134 | sprintf(dbpath, "%s/%s", path, |
511 | 7063 | dbinfo.name); | 7135 | dbinfo.name); |
512 | 7064 | srv_normalize_path_for_win(dbpath); | 7136 | srv_normalize_path_for_win(dbpath); |
513 | 7065 | 7137 | ||
514 | @@ -7076,18 +7148,19 @@ | |||
515 | 7076 | goto next_file_item_2; | 7148 | goto next_file_item_2; |
516 | 7077 | } | 7149 | } |
517 | 7078 | 7150 | ||
519 | 7079 | if (strlen(fileinfo.name) > 6 | 7151 | if (strlen(fileinfo.name) > suffix_len |
520 | 7080 | && 0 == strcmp(fileinfo.name + | 7152 | && 0 == strcmp(fileinfo.name + |
524 | 7081 | strlen(fileinfo.name) - 6, | 7153 | strlen(fileinfo.name) - |
525 | 7082 | ".delta")) { | 7154 | suffix_len, |
526 | 7083 | /* The name ends in .delta; try opening | 7155 | suffix)) { |
527 | 7156 | /* The name ends in suffix; process | ||
528 | 7084 | the file */ | 7157 | the file */ |
531 | 7085 | if (!xtrabackup_apply_delta( | 7158 | if (!func( |
532 | 7086 | xtrabackup_incremental_dir, | 7159 | path, |
533 | 7087 | dbinfo.name, | 7160 | dbinfo.name, |
535 | 7088 | fileinfo.name, check_newer)) | 7161 | fileinfo.name, data)) |
536 | 7089 | { | 7162 | { |
538 | 7090 | return FALSE; | 7163 | return(FALSE); |
539 | 7091 | } | 7164 | } |
540 | 7092 | } | 7165 | } |
541 | 7093 | next_file_item_2: | 7166 | next_file_item_2: |
542 | @@ -7100,13 +7173,24 @@ | |||
543 | 7100 | } | 7173 | } |
544 | 7101 | next_datadir_item: | 7174 | next_datadir_item: |
545 | 7102 | ret = fil_file_readdir_next_file(&err, | 7175 | ret = fil_file_readdir_next_file(&err, |
547 | 7103 | xtrabackup_incremental_dir, | 7176 | path, |
548 | 7104 | dir, &dbinfo); | 7177 | dir, &dbinfo); |
549 | 7105 | } | 7178 | } |
550 | 7106 | 7179 | ||
551 | 7107 | os_file_closedir(dir); | 7180 | os_file_closedir(dir); |
552 | 7108 | 7181 | ||
554 | 7109 | return TRUE; | 7182 | return(TRUE); |
555 | 7183 | } | ||
556 | 7184 | |||
557 | 7185 | /************************************************************************ | ||
558 | 7186 | Applies all .delta files from incremental_dir to the full backup. | ||
559 | 7187 | @return TRUE on success. */ | ||
560 | 7188 | static | ||
561 | 7189 | ibool | ||
562 | 7190 | xtrabackup_apply_deltas() | ||
563 | 7191 | { | ||
564 | 7192 | return xb_process_datadir(xtrabackup_incremental_dir, ".delta", | ||
565 | 7193 | xtrabackup_apply_delta, NULL); | ||
566 | 7110 | } | 7194 | } |
567 | 7111 | 7195 | ||
568 | 7112 | static my_bool | 7196 | static my_bool |
569 | @@ -7289,12 +7373,22 @@ | |||
570 | 7289 | goto error; | 7373 | goto error; |
571 | 7290 | } | 7374 | } |
572 | 7291 | 7375 | ||
574 | 7292 | if(!xtrabackup_apply_deltas(TRUE)) { | 7376 | inc_dir_tables_hash = hash_create(1000); |
575 | 7377 | |||
576 | 7378 | if(!xtrabackup_apply_deltas()) { | ||
577 | 7293 | xb_data_files_close(); | 7379 | xb_data_files_close(); |
578 | 7380 | xb_tables_hash_free(inc_dir_tables_hash); | ||
579 | 7294 | goto error; | 7381 | goto error; |
580 | 7295 | } | 7382 | } |
581 | 7296 | 7383 | ||
582 | 7297 | xb_data_files_close(); | 7384 | xb_data_files_close(); |
583 | 7385 | |||
584 | 7386 | /* Cleanup datadir from tablespaces deleted between full and | ||
585 | 7387 | incremental backups */ | ||
586 | 7388 | |||
587 | 7389 | xb_process_datadir("./", ".ibd", rm_if_not_found, NULL); | ||
588 | 7390 | |||
589 | 7391 | xb_tables_hash_free(inc_dir_tables_hash); | ||
590 | 7298 | } | 7392 | } |
591 | 7299 | sync_close(); | 7393 | sync_close(); |
592 | 7300 | sync_initialized = FALSE; | 7394 | sync_initialized = FALSE; |
593 | 7301 | 7395 | ||
594 | === added file 'test/t/bug856400.sh' | |||
595 | --- test/t/bug856400.sh 1970-01-01 00:00:00 +0000 | |||
596 | +++ test/t/bug856400.sh 2013-04-17 12:03:25 +0000 | |||
597 | @@ -0,0 +1,120 @@ | |||
598 | 1 | ######################################################################## | ||
599 | 2 | # Bug #856400: RENAME TABLE causes incremental prepare to fail | ||
600 | 3 | ######################################################################## | ||
601 | 4 | |||
602 | 5 | . inc/common.sh | ||
603 | 6 | . inc/ib_part.sh | ||
604 | 7 | |||
605 | 8 | start_server --innodb_file_per_table | ||
606 | 9 | |||
607 | 10 | require_partitioning | ||
608 | 11 | |||
609 | 12 | run_cmd $MYSQL $MYSQL_ARGS test <<EOF | ||
610 | 13 | CREATE TABLE t1(a INT) ENGINE=InnoDB; | ||
611 | 14 | INSERT INTO t1 VALUES (1), (2), (3); | ||
612 | 15 | |||
613 | 16 | CREATE TABLE t2(a INT) ENGINE=InnoDB; | ||
614 | 17 | INSERT INTO t2 VALUES (4), (5), (6); | ||
615 | 18 | |||
616 | 19 | CREATE TABLE p ( | ||
617 | 20 | a int | ||
618 | 21 | ) ENGINE=InnoDB | ||
619 | 22 | PARTITION BY RANGE (a) | ||
620 | 23 | (PARTITION p0 VALUES LESS THAN (100), | ||
621 | 24 | PARTITION p1 VALUES LESS THAN (200), | ||
622 | 25 | PARTITION p2 VALUES LESS THAN (300), | ||
623 | 26 | PARTITION p3 VALUES LESS THAN (400)); | ||
624 | 27 | |||
625 | 28 | INSERT INTO p VALUES (1), (101), (201), (301); | ||
626 | 29 | |||
627 | 30 | |||
628 | 31 | CREATE TABLE isam_t1(a INT) ENGINE=MyISAM; | ||
629 | 32 | INSERT INTO isam_t1 VALUES (1), (2), (3); | ||
630 | 33 | |||
631 | 34 | CREATE TABLE isam_t2(a INT) ENGINE=MyISAM; | ||
632 | 35 | INSERT INTO isam_t2 VALUES (4), (5), (6); | ||
633 | 36 | |||
634 | 37 | CREATE TABLE isam_p ( | ||
635 | 38 | a int | ||
636 | 39 | ) ENGINE=MyISAM | ||
637 | 40 | PARTITION BY RANGE (a) | ||
638 | 41 | (PARTITION p0 VALUES LESS THAN (100), | ||
639 | 42 | PARTITION p1 VALUES LESS THAN (200), | ||
640 | 43 | PARTITION p2 VALUES LESS THAN (300), | ||
641 | 44 | PARTITION p3 VALUES LESS THAN (400)); | ||
642 | 45 | |||
643 | 46 | INSERT INTO isam_p VALUES (1), (101), (201), (301); | ||
644 | 47 | |||
645 | 48 | EOF | ||
646 | 49 | |||
647 | 50 | # Full backup | ||
648 | 51 | vlog "Creating full backup" | ||
649 | 52 | innobackupex --no-timestamp $topdir/full | ||
650 | 53 | |||
651 | 54 | vlog "Making changes" | ||
652 | 55 | |||
653 | 56 | run_cmd $MYSQL $MYSQL_ARGS test <<EOF | ||
654 | 57 | |||
655 | 58 | DROP TABLE t1; | ||
656 | 59 | |||
657 | 60 | DROP TABLE t2; | ||
658 | 61 | CREATE TABLE t2(a INT) ENGINE=InnoDB; | ||
659 | 62 | INSERT INTO t2 VALUES (40), (50), (60); | ||
660 | 63 | |||
661 | 64 | ALTER TABLE p DROP PARTITION p0; | ||
662 | 65 | ALTER TABLE p DROP PARTITION p1; | ||
663 | 66 | ALTER TABLE p ADD PARTITION (PARTITION p4 VALUES LESS THAN (500)); | ||
664 | 67 | ALTER TABLE p ADD PARTITION (PARTITION p5 VALUES LESS THAN (600)); | ||
665 | 68 | |||
666 | 69 | INSERT INTO p VALUES (401), (501); | ||
667 | 70 | |||
668 | 71 | |||
669 | 72 | DROP TABLE isam_t1; | ||
670 | 73 | DROP TABLE isam_t2; | ||
671 | 74 | CREATE TABLE isam_t2(a INT) ENGINE=MyISAM; | ||
672 | 75 | |||
673 | 76 | INSERT INTO isam_t2 VALUES (40), (50), (60); | ||
674 | 77 | |||
675 | 78 | ALTER TABLE isam_p DROP PARTITION p0; | ||
676 | 79 | ALTER TABLE isam_p DROP PARTITION p1; | ||
677 | 80 | ALTER TABLE isam_p ADD PARTITION (PARTITION p4 VALUES LESS THAN (500)); | ||
678 | 81 | ALTER TABLE isam_p ADD PARTITION (PARTITION p5 VALUES LESS THAN (600)); | ||
679 | 82 | |||
680 | 83 | INSERT INTO isam_p VALUES (401), (501); | ||
681 | 84 | |||
682 | 85 | EOF | ||
683 | 86 | |||
684 | 87 | vlog "Creating incremental backup" | ||
685 | 88 | |||
686 | 89 | innobackupex --incremental --no-timestamp \ | ||
687 | 90 | --incremental-basedir=$topdir/full $topdir/inc | ||
688 | 91 | |||
689 | 92 | vlog "Preparing backup" | ||
690 | 93 | |||
691 | 94 | innobackupex --apply-log --redo-only $topdir/full | ||
692 | 95 | vlog "Log applied to full backup" | ||
693 | 96 | |||
694 | 97 | innobackupex --apply-log --redo-only --incremental-dir=$topdir/inc \ | ||
695 | 98 | $topdir/full | ||
696 | 99 | vlog "Delta applied to full backup" | ||
697 | 100 | |||
698 | 101 | innobackupex --apply-log $topdir/full | ||
699 | 102 | vlog "Data prepared for restore" | ||
700 | 103 | |||
701 | 104 | ls -al $topdir/full/test/* | ||
702 | 105 | |||
703 | 106 | # we expect to see | ||
704 | 107 | # 5 InnoDB tablespaces | ||
705 | 108 | count=`ls $topdir/full/test/*.ibd | wc -l` | ||
706 | 109 | vlog "$count .ibd in restore, expecting 5" | ||
707 | 110 | test $count -eq 5 | ||
708 | 111 | |||
709 | 112 | # 5 MyISAM data files | ||
710 | 113 | count=`ls $topdir/full/test/*.MYD | wc -l` | ||
711 | 114 | vlog "$count .MYD in restore, expecting 5" | ||
712 | 115 | test $count -eq 5 | ||
713 | 116 | |||
714 | 117 | # and 10 tables overall | ||
715 | 118 | count=`ls $topdir/full/test/*.frm | wc -l` | ||
716 | 119 | vlog "$count .frm in restore, expecting 4" | ||
717 | 120 | test $count -eq 4 |
http:// jenkins. percona. com/view/ XtraBackup/ job/percona- xtrabackup- 2.0-param/ 368/