Merge lp:~akopytov/percona-xtrabackup/bug803636-2.0 into lp:percona-xtrabackup/2.0
- bug803636-2.0
- Merge into 2.0
Proposed by
Alexey Kopytov
Status: | Merged | ||||
---|---|---|---|---|---|
Approved by: | Laurynas Biveinis | ||||
Approved revision: | no longer in the source branch. | ||||
Merged at revision: | 465 | ||||
Proposed branch: | lp:~akopytov/percona-xtrabackup/bug803636-2.0 | ||||
Merge into: | lp:percona-xtrabackup/2.0 | ||||
Diff against target: |
400 lines (+167/-28) 4 files modified
doc/source/innobackupex/how_innobackupex_works.rst (+7/-0) doc/source/innobackupex/innobackupex_option_reference.rst (+7/-1) innobackupex (+122/-27) test/t/bug803636.sh (+31/-0) |
||||
To merge this branch: | bzr merge lp:~akopytov/percona-xtrabackup/bug803636-2.0 | ||||
Related bugs: |
|
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Laurynas Biveinis (community) | Approve | ||
Review via email: mp+123040@code.launchpad.net |
Commit message
Description of the change
To post a comment you must log in.
Revision history for this message
Alexey Kopytov (akopytov) wrote : | # |
Revision history for this message
Laurynas Biveinis (laurynas-biveinis) : | # |
review:
Approve
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'doc/source/innobackupex/how_innobackupex_works.rst' |
2 | --- doc/source/innobackupex/how_innobackupex_works.rst 2012-02-14 08:31:46 +0000 |
3 | +++ doc/source/innobackupex/how_innobackupex_works.rst 2012-09-06 09:53:29 +0000 |
4 | @@ -71,3 +71,10 @@ |
5 | |innobackupex| will read the read from the :file:`my.cnf` the variables :term:`datadir`, :term:`innodb_data_home_dir`, :term:`innodb_data_file_path`, :term:`innodb_log_group_home_dir` and check that the directories exist. |
6 | |
7 | It will copy the |MyISAM| tables, indexes, etc. (:term:`.frm`, :term:`.MRG`, :term:`.MYD`, :term:`.MYI`, :term:`.TRG`, :term:`.TRN`, :term:`.ARM`, :term:`.ARZ`, :term:`.CSM`, :term:`.CSV` and :term:`.opt` files) first, |InnoDB| tables and indexes next and the log files at last. It will preserve file's attributes when copying them, you may have to change the files' ownership to ``mysql`` before starting the database server, as they will be owned by the user who created the backup. |
8 | + |
9 | +Alternatively, the :option:`--move-back` option may be used to restore a |
10 | +backup. This option is similar to :option:`--copy-back` with the only |
11 | +difference that instead of copying files it moves them to their target |
12 | +locations. As this option removes backup files, it must be used with |
13 | +caution. It is useful in cases when there is not enough free disk space |
14 | +to hold both data files and their backup copies. |
15 | |
16 | === modified file 'doc/source/innobackupex/innobackupex_option_reference.rst' |
17 | --- doc/source/innobackupex/innobackupex_option_reference.rst 2012-08-02 12:38:15 +0000 |
18 | +++ doc/source/innobackupex/innobackupex_option_reference.rst 2012-09-06 09:53:29 +0000 |
19 | @@ -30,6 +30,12 @@ |
20 | |
21 | Copy all the files in a previously made backup from the backup directory to their original locations. |
22 | |
23 | +.. option:: --move-back |
24 | + |
25 | + Move all the files in a previously made backup from the backup |
26 | + directory to their original locations. As this option removes |
27 | + backup files, it must be used with caution. |
28 | + |
29 | .. option:: --include=REGEXP |
30 | |
31 | This option is a regular expression to be matched against table names in ``databasename.tablename`` format. It is passed directly to :program:`xtrabackup` 's :option:`xtrabackup --tables` option. See the :program:`xtrabackup` documentation for details. |
32 | @@ -101,7 +107,7 @@ |
33 | |
34 | .. option:: --ibbackup = 'autodetect' |
35 | |
36 | - This option accepts a string argument that specifies which xtrabackup binary should be used. The string should be the command used to run *XtraBackup*. The option can be useful if the :program:`xtrabackup` binary is not in your search path or working directory and the database server is not accessible at the moment. If this option is not specified, :program:`innobackupex` attempts to determine the binary to use automatically. By default, :program:`xtrabackup` is the command used. When option :option:`--apply-log` is specified, the binary is used whose name is in the file :file:`xtrabackup_binary` in the backup directory, if that file exists, or will attempt to autodetect it. However, if :option:`--copy-back` is selected, :program:`xtrabackup` is used unless other is specified. |
37 | + This option accepts a string argument that specifies which xtrabackup binary should be used. The string should be the command used to run *XtraBackup*. The option can be useful if the :program:`xtrabackup` binary is not in your search path or working directory and the database server is not accessible at the moment. If this option is not specified, :program:`innobackupex` attempts to determine the binary to use automatically. By default, :program:`xtrabackup` is the command used. When option :option:`--apply-log` is specified, the binary is used whose name is in the file :file:`xtrabackup_binary` in the backup directory, if that file exists, or will attempt to autodetect it. However, if :option:`--copy-back` or :option:`--move-back` is used, :program:`xtrabackup` is used unless other is specified. |
38 | |
39 | .. option:: --incremental |
40 | |
41 | |
42 | === modified file 'innobackupex' |
43 | --- innobackupex 2012-08-02 12:38:15 +0000 |
44 | +++ innobackupex 2012-09-06 09:53:29 +0000 |
45 | @@ -72,6 +72,7 @@ |
46 | my $option_apply_log = ''; |
47 | my $option_redo_only = ''; |
48 | my $option_copy_back = ''; |
49 | +my $option_move_back = ''; |
50 | my $option_include = ''; |
51 | my $option_databases = ''; |
52 | my $option_tables_file = ''; |
53 | @@ -237,7 +238,7 @@ |
54 | print_version(); |
55 | |
56 | # initialize global variables and perform some checks |
57 | -if ($option_copy_back) { |
58 | +if ($option_copy_back || $option_move_back) { |
59 | $option_ibbackup_binary = 'xtrabackup' if ($option_ibbackup_binary eq 'autodetect'); |
60 | } elsif ($option_apply_log) { |
61 | # Read XtraBackup version from backup dir |
62 | @@ -279,7 +280,10 @@ |
63 | |
64 | if ($option_copy_back) { |
65 | # copy files from backup directory back to their original locations |
66 | - copy_back(); |
67 | + copy_back(0); |
68 | +} elsif ($option_move_back) { |
69 | + # move files from backup directory back to their original locations |
70 | + copy_back(1); |
71 | } elsif ($option_apply_log) { |
72 | # expand data files in backup directory by applying log files to them |
73 | apply_log(); |
74 | @@ -574,10 +578,41 @@ |
75 | } |
76 | |
77 | # |
78 | -# Callback function for copy_dir_recursively that actually does all |
79 | -# the copying work |
80 | -# |
81 | -sub copy_file() { |
82 | +# copy() wrapper with error handling |
83 | +# |
84 | +sub copy_file { |
85 | + my $src_path = shift; |
86 | + my $dst_path = shift; |
87 | + |
88 | + print STDERR "$prefix Copying '$src_path' to '$dst_path'\n"; |
89 | + copy($src_path, $dst_path) or Die "copy failed: $!"; |
90 | +} |
91 | + |
92 | +# |
93 | +# move() wrapper with error handling |
94 | +# |
95 | +sub move_file { |
96 | + my $src_path = shift; |
97 | + my $dst_path = shift; |
98 | + |
99 | + print STDERR "$prefix Moving '$src_path' to '$dst_path'\n"; |
100 | + move($src_path, $dst_path) or Die "move failed: $!"; |
101 | +} |
102 | + |
103 | + |
104 | +# |
105 | +# Auxiliary function called from find() callbacks to copy or move files and create directories |
106 | +# when necessary. |
107 | +# |
108 | +# SYNOPSIS |
109 | +# |
110 | +# process_file(\&process_func); |
111 | +# |
112 | +# &process_func is a code reference that does the actual file operation |
113 | +# |
114 | +sub process_file { |
115 | + my $process_func = shift; |
116 | + |
117 | if (/$copy_dir_exclude_regexp/) { |
118 | return; |
119 | } |
120 | @@ -593,16 +628,29 @@ |
121 | } else { |
122 | # Don't overwrite files unless $copy_dir_overwrite is 1 |
123 | if (!$copy_dir_overwrite && -e "$copy_dir_dst/$_") { |
124 | - Die "Failed to copy file $File::Find::name: " . |
125 | - "file $copy_dir_dst/$_ exists"; |
126 | + Die "Failed to process file $File::Find::name: " . |
127 | + "not overwriting file $copy_dir_dst/$_"; |
128 | } |
129 | |
130 | - print STDERR "$prefix Copying '$File::Find::name' to '$dst_path'\n"; |
131 | - copy($File::Find::name, $dst_path) or Die "copy failed: $!"; |
132 | + &$process_func($File::Find::name, $dst_path); |
133 | } |
134 | } |
135 | |
136 | # |
137 | +# find() callback to copy files |
138 | +# |
139 | +sub copy_file_callback { |
140 | + process_file(\©_file); |
141 | +} |
142 | + |
143 | +# |
144 | +# find() callback to move files |
145 | +# |
146 | +sub move_file_callback { |
147 | + process_file(\&move_file); |
148 | +} |
149 | + |
150 | +# |
151 | # copy_dir_recursively subroutine does a recursive copy of a specified |
152 | # directory excluding files matching a specifies regexp. If $overwrite |
153 | # is 1, it overwrites the existing files. |
154 | @@ -623,7 +671,29 @@ |
155 | $copy_dir_exclude_regexp = shift; |
156 | $copy_dir_overwrite = shift; |
157 | |
158 | - find(\©_file, $copy_dir_src); |
159 | + find(\©_file_callback, $copy_dir_src); |
160 | +} |
161 | + |
162 | +# |
163 | +# Similar to copy_dir_recursively, but moves files instead. |
164 | +# |
165 | +# SYNOPSIS |
166 | +# |
167 | +# move_dir_recursively($src_dir, $dst_dir, $exclude_regexp, |
168 | +# $overwrite); |
169 | +# |
170 | +# TODO |
171 | +# |
172 | +# use rsync when --rsync is specified |
173 | +# |
174 | +sub move_dir_recursively { |
175 | + # Clean paths and remove trailing slashes if any |
176 | + $copy_dir_src = File::Spec->canonpath(shift); |
177 | + $copy_dir_dst = File::Spec->canonpath(shift); |
178 | + $copy_dir_exclude_regexp = shift; |
179 | + $copy_dir_overwrite = shift; |
180 | + |
181 | + find(\&move_file_callback, $copy_dir_src); |
182 | } |
183 | |
184 | # |
185 | @@ -631,6 +701,7 @@ |
186 | # back to their original locations. |
187 | # |
188 | sub copy_back { |
189 | + my $move_flag = shift; |
190 | my $orig_datadir = get_option(\%config, $option_defaults_group, 'datadir'); |
191 | my $orig_ibdata_dir = |
192 | get_option(\%config, $option_defaults_group, 'innodb_data_home_dir'); |
193 | @@ -647,6 +718,14 @@ |
194 | my $compressed_data_file = '.*\.ibz$'; |
195 | my $file; |
196 | my $backup_innodb_data_file_path; |
197 | + |
198 | + # check whether files should be copied or moved to dest directory |
199 | + my $move_or_copy_file = $move_flag ? \&move_file : \©_file; |
200 | + my $move_or_copy_dir = $move_flag ? |
201 | + \&move_dir_recursively : \©_dir_recursively; |
202 | + my $operation = $move_flag ? "move" : "copy"; |
203 | + |
204 | + |
205 | # check that original data directories exist and they are empty |
206 | if_directory_exists_and_empty($orig_datadir, "Original data"); |
207 | if_directory_exists_and_empty($orig_ibdata_dir, "Original InnoDB data"); |
208 | @@ -678,7 +757,8 @@ |
209 | Die "Backup data file '$backup_dir/$filename' does not exist, but " |
210 | . "its compressed copy '${path}.ibz' exists. Check " |
211 | . "that you have run '$innobackup_script --apply-log --uncompress " |
212 | - . "...' before attempting '$innobackup_script --copy-back ...' !"; |
213 | + . "...' before attempting '$innobackup_script --copy-back ...' " |
214 | + . "or '$innobackup_script --move-back ...' !"; |
215 | } else { |
216 | Die "Backup data file '$backup_dir/$filename' does not exist."; |
217 | } |
218 | @@ -691,38 +771,34 @@ |
219 | |
220 | # copy files to original data directory |
221 | my $excluded_regexp = '^(' . $excluded_files . ')$'; |
222 | - print STDERR "$prefix Starting to copy files in '$backup_dir'\n"; |
223 | + print STDERR "$prefix Starting to $operation files in '$backup_dir'\n"; |
224 | print STDERR "$prefix back to original data directory '$orig_datadir'\n"; |
225 | - copy_dir_recursively($backup_dir, $orig_datadir, $excluded_regexp, 0); |
226 | + &$move_or_copy_dir($backup_dir, $orig_datadir, $excluded_regexp, 0); |
227 | |
228 | # copy InnoDB data files to original InnoDB data directory |
229 | - print STDERR "\n$prefix Starting to copy InnoDB system tablespace\n"; |
230 | + print STDERR "\n$prefix Starting to $operation InnoDB system tablespace\n"; |
231 | print STDERR "$prefix in '$backup_dir'\n"; |
232 | print STDERR "$prefix back to original InnoDB data directory '$orig_ibdata_dir'\n"; |
233 | foreach my $a (split(/;/, $orig_innodb_data_file_path)) { |
234 | # get the relative pathname of a data file |
235 | my $path = (split(/:/,$a))[0]; |
236 | my $filename = (split(/\/+/, $path))[-1]; |
237 | - print STDERR "$prefix Copying file '$backup_dir/$filename'\n"; |
238 | $src_name = escape_path("$backup_dir/$filename"); |
239 | $dst_name = escape_path("$orig_ibdata_dir/$path"); |
240 | - system("$CP_CMD \"$src_name\" \"$dst_name\"") |
241 | - and Die "Failed to copy file '$filename': $!"; |
242 | + &$move_or_copy_file($src_name, $dst_name); |
243 | } |
244 | |
245 | # copy InnoDB log files to original InnoDB log directory |
246 | opendir(DIR, $backup_dir) |
247 | || Die "Can't open directory '$backup_dir': $!\n"; |
248 | - print STDERR "\n$prefix Starting to copy InnoDB log files\n"; |
249 | + print STDERR "\n$prefix Starting to $operation InnoDB log files\n"; |
250 | print STDERR "$prefix in '$backup_dir'\n"; |
251 | print STDERR "$prefix back to original InnoDB log directory '$orig_iblog_dir'\n"; |
252 | while (defined($file = readdir(DIR))) { |
253 | if ($file =~ /'^' . $iblog_files . '$'/ && -f "$backup_dir/$file") { |
254 | - print STDERR "$prefix Copying file '$backup_dir/$file'\n"; |
255 | $src_name = escape_path("$backup_dir/$file"); |
256 | $dst_name = escape_path("$orig_iblog_dir"); |
257 | - system("$CP_CMD \"$src_name\" \"$dst_name\"") |
258 | - and Die "Failed to copy file '$file': $!"; |
259 | + &$move_or_copy_file($src_name, $dst_name); |
260 | } |
261 | } |
262 | closedir(DIR); |
263 | @@ -1528,10 +1604,12 @@ |
264 | my $run = ''; |
265 | |
266 | # print some instructions to the user |
267 | - if (!$option_apply_log && !$option_copy_back) { |
268 | + if (!$option_apply_log && !$option_copy_back && !$option_move_back) { |
269 | $run = 'backup'; |
270 | } elsif ($option_copy_back) { |
271 | $run = 'copy-back'; |
272 | + } elsif ($option_move_back) { |
273 | + $run = 'move-back'; |
274 | } else { |
275 | $run = 'apply-log'; |
276 | } |
277 | @@ -1541,7 +1619,7 @@ |
278 | |
279 | # check that MySQL client program and InnoDB Hot Backup program |
280 | # are runnable via shell |
281 | - if (!$option_copy_back) { |
282 | + if (!$option_copy_back && !$option_move_back) { |
283 | # we are making a backup or applying log to backup |
284 | if (!$option_apply_log) { |
285 | # we are making a backup, we need mysql server |
286 | @@ -1589,7 +1667,7 @@ |
287 | #$innodb_log_group_home_dir = |
288 | # get_option(\%config, 'mysqld', 'innodb_log_group_home_dir'); |
289 | |
290 | - if (!$option_apply_log && !$option_copy_back) { |
291 | + if (!$option_apply_log && !$option_copy_back && !$option_move_back) { |
292 | # we are making a backup, create a new backup directory |
293 | if (!$option_remote_host) { |
294 | $backup_dir = File::Spec->rel2abs(make_backup_dir()); |
295 | @@ -1619,7 +1697,7 @@ |
296 | } |
297 | } |
298 | write_backup_config_file($backup_config_file); |
299 | - } elsif ($option_copy_back) { |
300 | + } elsif ($option_copy_back || $option_move_back) { |
301 | #$backup_config_file = $backup_dir . '/backup-my.cnf'; |
302 | #read_config_file($backup_config_file, \%backup_config); |
303 | } |
304 | @@ -1715,6 +1793,7 @@ |
305 | 'apply-log' => \$option_apply_log, |
306 | 'redo-only' => \$option_redo_only, |
307 | 'copy-back' => \$option_copy_back, |
308 | + 'move-back' => \$option_move_back, |
309 | 'include=s' => \$option_include, |
310 | 'databases=s' => \$option_databases, |
311 | 'tables-file=s', => \$option_tables_file, |
312 | @@ -1765,6 +1844,11 @@ |
313 | exit(0); |
314 | } |
315 | |
316 | + if ($option_copy_back && $option_move_back) { |
317 | + print STDERR "$prefix --copy-back and --move-back options are " . |
318 | + "mutually exclusive"; |
319 | + } |
320 | + |
321 | if ($option_compress == 0) { |
322 | # compression level no specified, use default level |
323 | $option_compress = $default_compression_level; |
324 | @@ -1792,7 +1876,7 @@ |
325 | # get options file name |
326 | #$config_file = $ARGV[0]; |
327 | |
328 | - if (!$option_apply_log && !$option_copy_back) { |
329 | + if (!$option_apply_log && !$option_copy_back && !$option_move_back) { |
330 | # we are making a backup, get backup root directory |
331 | $backup_root = $ARGV[0]; |
332 | if ($option_incremental && !$option_incremental_lsn) { |
333 | @@ -2635,6 +2719,8 @@ |
334 | |
335 | innobackupex --copy-back [--defaults-file=MY.CNF] [--defaults-group=GROUP-NAME] BACKUP-DIR |
336 | |
337 | +innobackupex --move-back [--defaults-file=MY.CNF] [--defaults-group=GROUP-NAME] BACKUP-DIR |
338 | + |
339 | =head1 DESCRIPTION |
340 | |
341 | The first command line above makes a hot backup of a MySQL database. |
342 | @@ -2663,6 +2749,11 @@ |
343 | The MY.CNF options file defines the original location of the database. |
344 | The BACKUP-DIR is the path to a backup directory created by xtrabackup. |
345 | |
346 | +The --move-back command is similar to --copy-back with the only difference that |
347 | +it moves files to their original locations rather than copies them. As this |
348 | +option removes backup files, it must be used with caution. It may be useful in |
349 | +cases when there is not enough free disk space to copy files. |
350 | + |
351 | On success the exit code innobackupex is 0. A non-zero exit code |
352 | indicates an error. |
353 | |
354 | @@ -2691,6 +2782,10 @@ |
355 | |
356 | Copy all the files in a previously made backup from the backup directory to their original locations. |
357 | |
358 | +=item --move-back |
359 | + |
360 | +Move all the files in a previously made backup from the backup directory to the actual datadir location. Use with caution, as it removes backup files. |
361 | + |
362 | =item --databases=LIST |
363 | |
364 | This option specifies the list of databases that innobackupex should back up. The option accepts a string argument. The list is of the form "databasename1[.table_name1] databasename2[.table_name2] . . .". If this option is not specified, all databases containing MyISAM and InnoDB tables will be backed up. Please make sure that --databases contains all of the InnoDB databases and tables, so that all of the innodb.frm files are also backed up. In case the list is very long, this can be specified in a file, and the full path of the file can be specified instead of the list. (See option --tables-file.) |
365 | |
366 | === added file 'test/t/bug803636.sh' |
367 | --- test/t/bug803636.sh 1970-01-01 00:00:00 +0000 |
368 | +++ test/t/bug803636.sh 2012-09-06 09:53:29 +0000 |
369 | @@ -0,0 +1,31 @@ |
370 | +######################################################################## |
371 | +# Bug #803636: "moves files" option needed with --copy-back |
372 | +######################################################################## |
373 | + |
374 | +. inc/common.sh |
375 | + |
376 | +start_server --innodb_file_per_table |
377 | + |
378 | +load_sakila |
379 | + |
380 | +# Backup |
381 | +innobackupex --no-timestamp $topdir/backup |
382 | + |
383 | +stop_server |
384 | + |
385 | +rm -r $mysql_datadir |
386 | + |
387 | +# Prepare |
388 | +innobackupex --apply-log $topdir/backup |
389 | + |
390 | +# Restore |
391 | +mkdir -p $mysql_datadir |
392 | +innobackupex --move-back $topdir/backup |
393 | + |
394 | +# Check that there are no data files in the backup directory |
395 | +run_cmd_expect_failure ls -R $topdir/backup/*/*.{ibd,MYD,MYI,frm} |
396 | + |
397 | +start_server |
398 | + |
399 | +# Verify data |
400 | +run_cmd ${MYSQL} ${MYSQL_ARGS} -e "SELECT count(*) from actor" sakila |
http:// jenkins. percona. com/view/ XtraBackup/ job/percona- xtrabackup- 2.0-param/ 256/