3
# A script for making backups of InnoDB and MyISAM tables, indexes and .frm
6
# Copyright 2003, 2009 Innobase Oy. All Rights Reserved.
13
use POSIX ":sys_wait_h";
17
use English qw(-no_match_vars);
19
# version of this script
20
my $innobackup_version = '1.5.1-xtrabackup';
21
my $innobackup_script = basename($0);
24
my $copyright_notice =
25
"InnoDB Backup Utility v${innobackup_version}; Copyright 2003, 2009 Innobase Oy.
28
This software is published under
29
the GNU GENERAL PUBLIC LICENSE Version 2, June 1991.
33
# required Perl version (5.005)
34
my @required_perl_version = (5, 0, 5);
35
my $required_perl_version_old_style = 5.005;
37
# force flush after every write and print
40
######################################################################
41
# modifiable parameters
42
######################################################################
44
# maximum number of files in a database directory which are
45
# separately printed when a backup is made
46
my $backup_file_print_limit = 9;
48
# timeout in seconds for a reply from mysql
49
my $mysql_response_timeout = 900;
51
# default compression level (this is an argument to ibbackup)
52
my $default_compression_level = 1;
54
# time in seconds after which a dummy query is sent to mysql server
55
# in order to keep the database connection alive
56
my $mysql_keep_alive_timeout = 1800;
58
######################################################################
59
# end of modifiable parameters
60
######################################################################
63
# command line options
65
my $option_version = '';
66
my $option_apply_log = '';
67
my $option_redo_only = '';
68
my $option_copy_back = '';
69
my $option_include = '';
70
my $option_databases = '';
71
my $option_tables_file = '';
72
my $option_throttle = '';
73
my $option_sleep = '';
74
my $option_compress = 999;
75
my $option_uncompress = '';
76
my $option_export = '';
77
my $option_use_memory = '';
78
my $option_mysql_password = '';
79
my $option_mysql_user = '';
80
my $option_mysql_port = '';
81
my $option_mysql_socket = '';
82
my $option_mysql_host = '';
83
my $option_no_timestamp = '';
84
my $option_slave_info = '';
85
my $option_no_lock = '';
86
my $option_ibbackup_binary = 'autodetect';
88
my $option_defaults_file = '';
89
my $option_incremental = '';
90
my $option_incremental_basedir = '';
91
my $option_incremental_dir = '';
92
my $option_incremental_lsn = '';
93
my $option_extra_lsndir = '';
94
my $option_remote_host = '';
95
my $option_stream = '';
96
my $option_tmpdir = '';
98
my $option_tar4ibd = '';
99
my $option_force_tar = '';
100
my $option_scp_opt = '-Cp -c arcfour';
102
my $option_parallel = '';
104
my $option_safe_slave_backup = '';
105
my $option_safe_slave_backup_timeout = 300;
107
# name of the my.cnf configuration file
108
#my $config_file = '';
110
# root of the backup directory
111
my $backup_root = '';
113
# backup directory pathname
116
# name of the ibbackup suspend-at-end file
117
my $suspend_file = '';
119
# name of the temporary transaction log file during the backup
120
my $tmp_logfile = '';
122
# home directory of innoDB log files
123
my $innodb_log_group_home_dir = '';
126
my $backup_config_file = '';
128
# options from the options file
131
# options from the backup options file
134
# list of databases to be included in a backup
137
# list of tables to be included in a backup
140
# prefix for output lines
141
my $prefix = "$innobackup_script:";
143
# process id of mysql client program (runs as a child process of this script)
146
# mysql server version string
147
my $mysql_server_version = '';
149
# name of the file where stderr of mysql process is directed
150
my $mysql_stderr = 'stderr';
152
# name of the file where stdout of mysql process is directed
153
my $mysql_stdout = 'stdout';
155
# name of the file where binlog position info is written
158
# name of the file where slave info is written
161
# mysql binlog position as given by "SHOW MASTER STATUS" command
162
my $mysql_binlog_position = '';
164
# mysql master's binlog position as given by "SHOW SLAVE STATUS" command
165
# run on a slave server
166
my $mysql_slave_position = '';
168
# time of the most recent mysql_check call. (value returned by time() function)
169
my $mysql_last_access_time = 0;
171
# process id of ibbackup program (runs as a child process of this script)
172
my $ibbackup_pid = '';
174
# a counter for numbering mysql connection checks
177
# the request which has been sent to mysqld, but to which
178
# mysqld has not yet replied. Empty string denotes that no
179
# request has been sent to mysqld or that mysqld has replied
181
my $current_mysql_request = '';
183
# escape sequences for options files
184
my %option_value_escapes = ('b' => "\b",
191
# signal that is sent to child processes when they are killed
192
my $kill_signal = 15;
197
# incremental backup base directory
198
my $incremental_basedir = '';
202
my $win = ($^O eq 'MSWin32' ? 1 : 0);
203
my $CP_CMD = ($win eq 1 ? "copy /Y" : "cp -p");
204
my $xtrabackup_binary_file = 'xtrabackup_binary';
205
######################################################################
206
# program execution begins here
207
######################################################################
209
# check command-line args
212
# print program version and copyright
215
# initialize global variables and perform some checks
216
if ($option_copy_back) {
217
$option_ibbackup_binary = 'xtrabackup_51';
218
} elsif ($option_apply_log) {
219
# Read XtraBackup version from backup dir
220
if (-e "$backup_dir/$xtrabackup_binary_file") {
221
# Read XtraBackup version from file
222
open XTRABACKUP_BINARY, "$backup_dir/$xtrabackup_binary_file"
223
or die "Cannot open file $backup_dir/$xtrabackup_binary_file: $!\n";
224
$option_ibbackup_binary = <XTRABACKUP_BINARY>;
225
close XTRABACKUP_BINARY;
229
if( $option_ibbackup_binary eq "autodetect" ){
230
# Try to connect MySQL and get the version
231
print "option_ibbackup_binary is autodetect, trying to connect to MySQL\n";
232
my $options = get_mysql_options();
233
$mysql_pid = open(*MYSQL_WRITER, "| mysql $options >$mysql_stdout 2>$mysql_stderr ");
234
print "Connected to MySQL with pid $mysql_pid\n";
236
if ($mysql_pid && $mysql_pid == waitpid($mysql_pid, &WNOHANG)) {
237
my $reason = `cat $mysql_stderr`;
239
# Failed to connect to MySQL
240
die "Failed to connect to MySQL server to detect version.\nYou must set xtrabackup version to use with --ibbackup option.\nPossible values are xtrabackup_51 (for MySQL 5.0 and 5.1) or xtrabackup (for MySQL 5.1 with InnoDB plugin or Percona Server)\n";
244
print "Connected successfully\n";
245
$option_ibbackup_binary = set_xtrabackup_version();
250
$option_ibbackup_binary = set_xtrabackup_version();
254
my $ibbackup_exit_code = 0;
256
if ($option_copy_back) {
257
# copy files from backup directory back to their original locations
259
} elsif ($option_apply_log) {
260
# expand data files in backup directory by applying log files to them
263
# make a backup of InnoDB and MyISAM tables, indexes and .frm files.
264
$ibbackup_exit_code = backup();
265
open XTRABACKUP_BINARY, "> $backup_dir/$xtrabackup_binary_file"
266
or die "Cannot open file $backup_dir/$xtrabackup_binary_file: $!\n";
267
print XTRABACKUP_BINARY $option_ibbackup_binary;
268
close XTRABACKUP_BINARY;
271
$now = current_time();
273
if ($option_stream eq 'tar') {
274
print STDERR "$prefix You must use -i (--ignore-zeros) option for extraction of the tar stream.\n";
277
if ( $ibbackup_exit_code == 0 ) {
278
# program has completed successfully
279
print STDERR "$now $prefix completed OK!\n";
282
print STDERR "$now $prefix $option_ibbackup_binary failed! (exit code $ibbackup_exit_code) The backup may not be complete.\n";
285
exit $ibbackup_exit_code;
287
######################################################################
288
# end of program execution
289
######################################################################
293
# print_version subroutine prints program version and copyright.
296
printf(STDERR $copyright_notice);
301
# usage subroutine prints instructions of how to use this program to stdout.
307
$innobackup_script [--sleep=MS] [--compress[=LEVEL]] [--include=REGEXP] [--user=NAME]
308
[--password=WORD] [--port=PORT] [--socket=SOCKET] [--no-timestamp]
309
[--ibbackup=IBBACKUP-BINARY] [--slave-info] [--stream=tar]
310
[--scpopt=OPTIONS-FOR-SCP]
311
[--defaults-file=MY.CNF]
312
[--databases=LIST] [--remote-host=HOSTNAME] [--no-lock] BACKUP-ROOT-DIR
313
$innobackup_script --apply-log [--use-memory=MB] [--uncompress] [--defaults-file=MY.CNF]
314
[--export] [--redo-only] [--ibbackup=IBBACKUP-BINARY] BACKUP-DIR
315
$innobackup_script --copy-back [--defaults-file=MY.CNF] BACKUP-DIR
317
The first command line above makes a hot backup of a MySQL database.
318
By default it creates a backup directory (named by the current date
319
and time) in the given backup root directory. With the --no-timestamp
320
option it does not create a time-stamped backup directory, but it puts
321
the backup in the given directory (which must not exist). This
322
command makes a complete backup of all MyISAM and InnoDB tables and
323
indexes in all databases or in all of the databases specified with the
324
--databases option. The created backup contains .frm, .MRG, .MYD,
325
.MYI, .TRG, .TRN, .ARM, .ARZ, .CSM, .CSV, .opt, .par, and InnoDB data and log files.
326
The MY.CNF options file defines the location of the database. This command
327
connects to the MySQL server using mysql client program, and runs
328
ibbackup (InnoDB Hot Backup program) as a child process.
330
The command with --apply-log option prepares a backup for starting a MySQL
331
server on the backup. This command expands InnoDB data files as specified
332
in BACKUP-DIR/backup-my.cnf using BACKUP-DIR/ibbackup_logfile,
333
and creates new InnoDB log files as specified in BACKUP-DIR/backup-my.cnf.
334
The BACKUP-DIR should be a path name of a backup directory created by
335
innobackup. This command runs ibbackup as a child process, but it does not
336
connect to the database server.
338
The command with --copy-back option copies data, index, and log files
339
from backup directory back to their original locations.
340
The MY.CNF options file defines the original location of the database.
341
The BACKUP-DIR is a path name of a backup directory created by innobackup.
343
On success the exit code of innobackup process is 0. A non-zero exit code
348
--help Display this helpscreen and exit.
350
--version Print version information and exit.
352
--defaults-file=[MY.CNF]
353
This option is passed to the xtrabackup child process.
354
It specify which file only read default options from.
356
--apply-log Prepare a backup for starting mysql server on the backup.
357
Expand InnoDB data files as specified in
358
backup-dir/backup-my.cnf, using backup-dir/ibbackup_logfile,
359
and create new log files as specified in
360
backup-dir/backup-my.cnf.
362
--redo-only Options is used with --apply-log. This option forces to skip
363
"rollback" phase and do only "redo". This is necessary to use
364
if backup later will be applied with incremental changes.
366
--copy-back Copy data and index files from backup directory back to
367
their original locations.
369
--remote-host=HOSTNAME
370
If this option is specified, backup files will be created
371
at the remote host by using ssh connection.
373
--stream=[tar|cpio(not implemented)]
374
If this option is specified, backup to STDOUT as specified
375
format. Uses tar4ibd (available in XtraBackup binary).
378
When --remote-host or --stream specified, transaction log
379
should be stored temporary. The default value is same to
383
This option is passed to the ibbackup child process.
384
It tells ibbackup that it can use MB megabytes of
385
memory in restoration.
386
Try 'ibbackup --help' for more details on this option.
388
--parallel=NUMBER-OF-THREADS
389
This option is passed to the xtrabackup child process.
390
It specifies the number of threads used by xtrabackup for
391
parallel data transfer. The default value is 1 (i.e. no
395
This option is passed to the xtrabackup child process.
396
It limits count of IO operations (pairs of read&write) per
397
second to IOS values (for '--backup')
399
--sleep=MS This option is passed to the ibbackup child process.
400
It instructs the ibbackup program to sleep
401
MS milliseconds after each 1 MB of copied data.
402
You can use this parameter to tune the additional
403
disk i/o load the ibbackup program causes on the computer.
404
Try 'ibbackup --help' for more details on this option.
405
** it is not supported by xtrabackup **
408
This option is passed to the ibbackup child process.
409
It instructs ibbackup to compress the backup copies of
410
InnoDB data files. Compression level can be
411
specified as an optional argument. Compression level is
412
an integer between 0 and 9: 1 gives fastest compression,
413
9 gives best compression, and 0 means no compression.
414
If compression level is not given, the default level 1 is used.
415
Try 'ibbackup --help' for more details on this option.
416
** it is not supported by xtrabackup yet **
419
This option is passed to the ibbackup child process.
420
It tells ibbackup to backup only those per-table data
421
files which match the given regular expression. For
422
each table with a per-table data file a string of the
423
form db_name.table_name is checked against the regular
424
expression. If the regular expression matches the
425
complete string db_name.table_name, the table is
426
included in the backup. The regular expression should
427
be of the POSIX 1003.2 "extended" form.
428
Try 'ibbackup --help' for more details on this option.
431
This option is used to specify the list of databases that
432
innobackup should backup. The list is of the form
433
"db_name[.table_name] db_name1[.table_name1] ...".
434
If this option is not specified all databases containing
435
MyISAM and InnoDB tables will be backed up.
436
Please make sure that --databases contains all of the
437
innodb databases & tables so that all of the innodb .frm
438
files are also backed up. In case the list is very long,
439
this can be specified in a file and the full path of the
440
file can be specified instead of the list.
443
This option is passed to xtrabackup --tables-file. It
444
filters the tables to backup by a list of database.table
445
names listed in the given file, one per line.
448
This option is passed to the ibbackup child process.
449
It tells ibbackup to uncompress compressed InnoDB data files.
450
Try 'ibbackup --help' for more details on this option.
451
** it is not supported by xtrabackup yet **
453
--export This option is passed to the xtrabackup child process.
454
It is effective with '--prepare' option.
455
It tells xtrabackup to output "clean" .ibd files and .exp
456
files for 'ALTER TABLE ... IMPORT TABLESPACE' command
457
at innodb_expand_import option enabled XtraDB.
459
--user=NAME This option is passed to the mysql child process.
460
It defines the user for database login if not current user.
461
Try 'mysql --help' for more details on this option.
464
This option is passed to the mysql child process.
465
It defines the password to use when connecting to database.
466
Try 'mysql --help' for more details on this option.
468
--host=HOST This option is passed to the mysql child process.
469
It defines the host to use when connecting to database
471
Try 'mysql --help' for more details on this option.
473
--port=PORT This option is passed to the mysql child process.
474
It defines the port to use when connecting to database
476
Try 'mysql --help' for more details on this option.
479
Stop slave SQL thread and wait to start backup until
480
Slave_open_temp_tables in SHOW STATUS is zero. If
481
there are no open temp tables, the backup will take place,
482
else the SQL thread will be started and stopped until there
483
are no open temp tables. The backup will fail if
484
Slave_open_temp_tables does not become zero after
485
--safe-slave-backup-timeout seconds. The slave SQL thread
486
will be restarted when the backup finishes.
488
--safe-slave-backup-timeout
489
How many seconds --safe-slave-backup should wait for
490
Slave_open_temp_tables to become zero. (default 300)
493
This option is useful when backing up a replication
494
slave server. It prints the binary log position and
495
name of the binary log file of the master server.
496
It also writes this information to the 'ibbackup_slave_info'
497
file as a 'CHANGE MASTER' command. A new slave for this
498
master can be set up by starting a slave server on this
499
backup and issuing a 'CHANGE MASTER' command with the binary
500
log position saved in the 'ibbackup_slave_info' file.
503
This option is passed to the mysql child process.
504
It defines the socket to use when connecting to local database
505
server with UNIX domain socket.
506
Try 'mysql --help' for more details on this option.
509
This option prevents the creation of a new backup
510
directory (named by the current date and time) under
511
the backup root directory. Instead, the backup is put
512
in the directory given on the command-line (in the
513
place of BACKUP-ROOT-DIR argument). The directory must not
514
exist, because innobackup creates it while making a backup.
516
--ibbackup=IBBACKUP-BINARY
517
Use this option to specify which ibbackup (InnoDB Hot
518
Backup) binary should be used. IBBACKUP-BINARY
519
should be the command used to run ibbackup. This can
520
be useful if ibbackup is not in your search path or
521
working directory. If this option is not given,
522
ibbackup is run with command "xtrabackup".
524
Use this option to disable table lock with
525
FLUSH TABLES WITH READ LOCK. use it only while ALL your
526
tables are InnoDB and you DO NOT CARE about binary log
530
Use this option to specify the command line options
531
to pass to scp. The default options are '-Cp -c arcfour'.
538
# return current local time as string in form "070816 12:23:15"
541
return strftime("%y%m%d %H:%M:%S", localtime());
546
# Die subroutine kills all child processes and exits this process.
547
# This subroutine takes the same argument as the built-in die function.
549
# message string which is printed to stdout
555
# kill all child processes of this process
556
kill_child_processes();
558
if ($current_mysql_request) {
559
$extra_info = " while waiting for reply to MySQL request:" .
560
" '$current_mysql_request'";
562
die "$prefix Error: $message$extra_info";
567
# backup subroutine makes a backup of InnoDB and MyISAM tables, indexes and
568
# .frm files. It connects to the database server and runs ibbackup as a child
572
my $orig_datadir = get_option(\%config, 'mysqld', 'datadir');
574
# check that we can connect to the database. This done by
575
# connecting, issuing a query, and closing the connection.
580
# start ibbackup as a child process
583
# wait for ibbackup to suspend itself
584
if (!$option_remote_host && !$option_stream) {
585
wait_for_ibbackup_suspend();
588
if (!$option_incremental) {
589
# connect to database
592
if ( $option_safe_slave_backup ) {
593
wait_for_safe_slave();
596
# flush tables with read lock
598
mysql_lockall() if !$option_no_lock;
602
# backup .frm, .MRG, .MYD, .MYI, .TRG, .TRN, .ARM, .ARZ, .CSM, .CSV and .opt files
605
# resume ibbackup and wait till it has finished
606
my $ibbackup_exit_code = resume_ibbackup();
608
if (!$option_incremental) {
609
# release read locks on all tables
610
mysql_unlockall() if !$option_no_lock;
612
if ( $option_safe_slave_backup ) {
613
print STDERR "$prefix: Starting slave SQL thread\n";
614
mysql_send('START SLAVE SQL_THREAD;');
617
# disconnect from database
621
if ($option_remote_host) {
622
system("scp $option_scp_opt '$tmp_logfile' '$option_remote_host:$backup_dir/xtrabackup_logfile'")
623
and Die "Failed to scp file '$option_remote_host:$backup_dir/xtrabackup_logfile': $!";
624
unlink $tmp_logfile || Die "Failed to delete '$tmp_logfile': $!";
626
system("scp $option_scp_opt '$orig_datadir/xtrabackup_checkpoints' '$option_remote_host:$backup_dir/xtrabackup_checkpoints'")
627
and Die "Failed to scp file '$option_remote_host:$backup_dir/xtrabackup_checkpoints': $!";
628
unlink "$orig_datadir/xtrabackup_checkpoints" || Die "Failed to delete '$orig_datadir/xtrabackup_checkpoints': $!";
629
} elsif ($option_stream eq 'tar') {
630
system("cd $option_tmpdir; tar chf - xtrabackup_logfile")
631
and Die "Failed to stream 'xtrabackup_logfile': $!";
632
unlink $tmp_logfile || Die "Failed to delete '$tmp_logfile': $!";
634
system("cd $orig_datadir; tar chf - xtrabackup_checkpoints")
635
and Die "Failed to stream 'xtrabackup_checkpoints': $!";
636
unlink "$orig_datadir/xtrabackup_checkpoints" || Die "Failed to delete '$orig_datadir/xtrabackup_checkpoints': $!";
639
print STDERR "\n$prefix Backup created in directory '$backup_dir'\n";
640
if ($mysql_binlog_position) {
641
print STDERR "$prefix MySQL binlog position: $mysql_binlog_position\n";
643
if ($mysql_slave_position && $option_slave_info) {
644
print STDERR "$prefix MySQL slave binlog position: $mysql_slave_position\n";
647
return $ibbackup_exit_code;
652
# are_equal_innodb_data_file_paths subroutine checks if the given
653
# InnoDB data file option values are equal.
655
# str1 InnoDB data file path option value
656
# str2 InnoDB data file path option value
658
# 1 if values are equal
661
sub are_equal_innodb_data_file_paths {
664
my @array1 = split(/;/, $str1);
665
my @array2 = split(/;/, $str2);
667
if ($#array1 != $#array2) { return 0; }
669
for (my $i = 0; $i <= $#array1; $i++) {
670
my @def1 = split(/:/, $array1[$i]);
671
my @def2 = split(/:/, $array2[$i]);
673
if ($#def1 != $#def2) { return 0; }
675
for (my $j = 0; $j <= $#def1; $j++) {
676
if ($def1[$j] ne $def2[$j]) { return 0; }
684
# is_in_array subroutine checks if the given string is in the array.
687
# array_ref a reference to an array of strings
689
# 1 if string is in the array
694
my $array_ref = shift;
696
if (grep { $str eq $_ } @{$array_ref}) {
704
# copy_back subroutine copies data and index files from backup directory
705
# back to their original locations.
708
my $orig_datadir = get_option(\%config, 'mysqld', 'datadir');
709
my $orig_ibdata_dir =
710
get_option(\%config, 'mysqld', 'innodb_data_home_dir');
711
my $orig_innodb_data_file_path =
712
get_option(\%config, 'mysqld', 'innodb_data_file_path');
714
get_option(\%config, 'mysqld', 'innodb_log_group_home_dir');
716
'^(\.\.?|backup-my\.cnf|xtrabackup_logfile|mysql-std(err|out)|.*\.ibz)$';
718
my $iblog_files = '^ib_logfile.*$';
719
my $compressed_data_file = '.*\.ibz$';
721
my $backup_innodb_data_file_path;
722
# check that original data directory exists
723
if (! -d $orig_datadir) {
724
Die "Original data directory '$orig_datadir' does not exist!";
726
# check that original InnoDB data directory exists
727
if (! -d $orig_ibdata_dir) {
728
Die "Original InnoDB data directory '$orig_ibdata_dir' does not exist!";
730
# check that original InnoDB log directory exists
731
if (! -d $orig_iblog_dir) {
732
Die "Original InnoDB log directory '$orig_iblog_dir' does not exist!";
735
# check that the original options file and the backup options file have
736
# the same value for "innodb_data_file_path" option
737
#$backup_innodb_data_file_path =
738
# get_option(\%backup_config, 'mysqld', 'innodb_data_file_path');
739
#if (!are_equal_innodb_data_file_paths($orig_innodb_data_file_path,
740
# $backup_innodb_data_file_path)
742
# Die "The value of 'innodb_data_file_path' option in the original "
743
# . "my.cnf file '$config_file' is different from the value "
744
# . "in the backup my.cnf file '$backup_config_file'.\n(original: "
745
# . "'$orig_innodb_data_file_path')\n"
746
# . "(backup: '$backup_innodb_data_file_path')";
749
# make a list of all ibdata files in the backup directory and all
750
# directories in the backup directory under which there are ibdata files
751
foreach my $a (split(/;/, $orig_innodb_data_file_path)) {
752
my $path = (split(/:/,$a))[0];
753
my $filename = (split(/\/+/, $path))[-1];
755
# check that the backup data file exists
756
if (! -e "$backup_dir/$filename") {
757
if (-e "$backup_dir/${filename}.ibz") {
758
Die "Backup data file '$backup_dir/$filename' does not exist, but "
759
. "its compressed copy '${path}.ibz' exists. Check "
760
. "that you have run '$innobackup_script --apply-log --uncompress "
761
. "...' before attempting '$innobackup_script --copy-back ...' !";
763
Die "Backup data file '$backup_dir/$filename' does not exist.";
767
if (!is_in_array($filename, \@ibdata_files)) {
768
push(@ibdata_files, $filename);
772
# copy files from backup dir to their original locations
774
# copy files to original data directory
775
opendir(DIR, $backup_dir)
776
|| Die "Can't open directory '$backup_dir': $!\n";
777
print STDERR "$prefix Starting to copy MyISAM tables, indexes,\n";
778
print STDERR "$prefix .MRG, .TRG, .TRN, .ARM, .ARZ, .CSM, .CSV, .opt, and .frm files\n";
779
print STDERR "$prefix in '$backup_dir'\n";
780
print STDERR "$prefix back to original data directory '$orig_datadir'\n";
781
while (defined($file = readdir(DIR))) {
782
if ($file =~ /$excluded_files/) { next; }
783
if (is_in_array($file, \@ibdata_files)) { next; }
784
if ($file =~ /$iblog_files/) { next; }
785
if (-d "$backup_dir/$file") {
786
my $subdir = "$backup_dir/$file";
789
print STDERR "$prefix Copying directory '$subdir'\n";
790
if (! -x "\"".escape_path("$orig_datadir/$file")."\"") {
791
system("mkdir \"".escape_path("$orig_datadir/$file")."\"")
792
and Die "Failed to create directory "
793
. "'$orig_datadir/$file' : $!";
795
opendir(SUBDIR, "$subdir")
796
|| Die "Can't open directory '$subdir': $!\n";
797
while (defined($file2 = readdir(SUBDIR))) {
798
if (-d "$subdir/$file2") { next; }
799
if ($file2 =~ /$compressed_data_file/) { next; }
800
$src_name = escape_path("$subdir/$file2");
801
$dst_name = escape_path("$orig_datadir/$file");
802
system("$CP_CMD \"$src_name\" \"$dst_name\"")
803
and Die "Failed to copy file '$file': $!";
807
print STDERR "$prefix Copying file " .
808
"'$backup_dir/$file'\n";
809
$src_name = escape_path("$backup_dir/$file");
810
$dst_name = escape_path("$orig_datadir");
811
system("$CP_CMD \"$src_name\" \"$dst_name\"")
812
and Die "Failed to copy file '$file': $!";
817
# copy InnoDB data files to original InnoDB data directory
818
print STDERR "\n$prefix Starting to copy InnoDB tables and indexes\n";
819
print STDERR "$prefix in '$backup_dir'\n";
820
print STDERR "$prefix back to original InnoDB data directory '$orig_ibdata_dir'\n";
821
foreach my $a (split(/;/, $orig_innodb_data_file_path)) {
822
# get the relative pathname of a data file
823
my $path = (split(/:/,$a))[0];
824
my $filename = (split(/\/+/, $path))[-1];
825
print STDERR "$prefix Copying file '$backup_dir/$filename'\n";
826
$src_name = escape_path("$backup_dir/$filename");
827
$dst_name = escape_path("$orig_ibdata_dir/$path");
828
system("$CP_CMD \"$src_name\" \"$dst_name\"")
829
and Die "Failed to copy file '$filename': $!";
832
# copy InnoDB log files to original InnoDB log directory
833
opendir(DIR, $backup_dir)
834
|| Die "Can't open directory '$backup_dir': $!\n";
835
print STDERR "\n$prefix Starting to copy InnoDB log files\n";
836
print STDERR "$prefix in '$backup_dir'\n";
837
print STDERR "$prefix back to original InnoDB log directory '$orig_iblog_dir'\n";
838
while (defined($file = readdir(DIR))) {
839
if ($file =~ /$iblog_files/ && -f "$backup_dir/$file") {
840
print STDERR "$prefix Copying file '$backup_dir/$file'\n";
841
$src_name = escape_path("$backup_dir/$file");
842
$dst_name = escape_path("$orig_iblog_dir");
843
system("$CP_CMD \"$src_name\" \"$dst_name\"")
844
and Die "Failed to copy file '$file': $!";
849
print STDERR "$prefix Finished copying back files.\n\n";
854
# apply_log subroutine prepares a backup for starting database server
855
# on the backup. It applies InnoDB log files to the InnoDB data files.
862
if ($option_defaults_file) {
863
$options = $options . " --defaults-file=\"$option_defaults_file\" ";
866
$options = $options . "--prepare --target-dir=$backup_dir";
868
if ($option_uncompress) {
869
$options = $options . ' --uncompress';
871
if ($option_export) {
872
$options = $options . ' --export';
874
if ($option_redo_only) {
875
$options = $options . ' --apply-log-only';
877
if ($option_use_memory) {
878
$options = $options . " --use-memory=$option_use_memory";
881
if ($option_incremental_dir) {
882
$options = $options . " --incremental-dir=$option_incremental_dir";
885
# run ibbackup as a child process
886
$cmdline = "$option_ibbackup_binary $options";
887
$now = current_time();
888
print STDERR "\n$now $prefix Starting ibbackup with command: $cmdline\n\n";
889
$rcode = system("$cmdline");
892
Die "\n$prefix ibbackup failed";
895
# We should not create ib_logfile files if we prepare for following incremental applies
896
# Also we do not prepare ib_logfile if we applied incremental changes
897
if (!( ($option_redo_only) or ($option_incremental_dir))) {
898
$now = current_time();
899
print STDERR "\n$now $prefix Restarting xtrabackup with command: $cmdline\nfor creating ib_logfile*\n\n";
900
$rcode = system("$cmdline");
903
Die "\n$prefix xtrabackup (2nd execution) failed";
910
# wait_for_ibbackup_suspend subroutine waits until ibbackup has suspended
913
sub wait_for_ibbackup_suspend {
914
print STDERR "$prefix Waiting for ibbackup (pid=$ibbackup_pid) to suspend\n";
915
print STDERR "$prefix Suspend file '$suspend_file'\n\n";
918
last if -e $suspend_file;
920
# check that ibbackup child process is still alive
921
if ($ibbackup_pid == waitpid($ibbackup_pid, &WNOHANG)) {
923
Die "ibbackup child process has died";
926
$now = current_time();
927
print STDERR "\n$now $prefix Continuing after ibbackup has suspended\n";
932
# resume_ibbackup subroutine signals ibbackup to complete its execution
933
# by deleting the 'ibbackup_suspended' file.
935
sub resume_ibbackup {
936
print STDERR "$prefix Resuming ibbackup\n\n";
937
unlink $suspend_file || Die "Failed to delete '$suspend_file': $!";
939
# wait for ibbackup to finish
940
waitpid($ibbackup_pid, 0);
942
return $CHILD_ERROR >> 8;
947
# start_ibbackup subroutine spawns a child process running ibbackup
948
# program for backing up InnoDB tables and indexes.
955
if ($option_defaults_file) {
956
$options = $options . " --defaults-file=\"$option_defaults_file\" ";
959
$options = $options . "--backup --suspend-at-end";
961
if (!$option_remote_host && !$option_stream) {
962
$options = $options . " --target-dir=$backup_dir";
964
#(datadir) for 'xtrabackup_suspended' and 'xtrabackup_checkpoints'
965
$options = $options . " --log-stream --target-dir=./";
968
# prepare command line for running ibbackup
969
if ($option_throttle) {
970
$options = $options . " --throttle=$option_throttle";
973
$options = $options . " --sleep=$option_sleep";
975
if ($option_compress) {
976
$options = $options . " --compress=$option_compress";
978
if ($option_use_memory) {
979
$options = $options . " --use-memory=$option_use_memory";
981
if ($option_include) {
982
$options = $options . " --tables='$option_include'";
984
if ($option_extra_lsndir) {
985
$options = $options . " --extra-lsndir='$option_extra_lsndir'";
988
if ($option_incremental) {
989
if($option_incremental_lsn) {
990
$options = $options . " --incremental-lsn='$option_incremental_lsn'";
992
$options = $options . " --incremental-basedir='$incremental_basedir'";
996
if ($option_tables_file) {
997
$options = $options . " --tables_file='$option_tables_file'";
999
if ($option_parallel) {
1000
$options = $options. " --parallel=$option_parallel";
1002
$cmdline = "$option_ibbackup_binary $options";
1004
# run ibbackup as a child process
1005
$now = current_time();
1006
print STDERR "\n$now $prefix Starting ibbackup with command: $cmdline\n";
1007
if (defined($pid = fork)) {
1010
$ibbackup_pid = $pid;
1012
if($option_remote_host || $option_stream) {
1013
#direct copy to remote
1014
my $orig_datadir = get_option(\%config, 'mysqld', 'datadir');
1015
my $orig_ibdata_dir =
1016
get_option(\%config, 'mysqld', 'innodb_data_home_dir');
1017
my $orig_innodb_data_file_path =
1018
get_option(\%config, 'mysqld', 'innodb_data_file_path');
1019
my $innodb_flush_method =
1020
get_option(\%config, 'mysqld', 'innodb_flush_method');
1021
my $innodb_use_odirect;
1022
$innodb_use_odirect = 1 if $innodb_flush_method =~ m/O_DIRECT/i;
1027
if($option_remote_host) {
1028
if (system("ssh $option_remote_host test -e $backup_dir/ib_logfile0")
1030
print STDERR "$prefix Remove $option_remote_host:$backup_dir/ib_logfile*\n";
1031
system("ssh $option_remote_host rm $backup_dir/ib_logfile\*")
1032
and Die "Failed to rm file '$backup_dir/ib_logfile*': $!";
1036
wait_for_ibbackup_suspend();
1038
#InnoDB data files from original InnoDB data directory
1039
print STDERR "\n$prefix Starting to backup InnoDB tables and indexes\n";
1040
if($option_remote_host) {
1041
print STDERR "$prefix to '$backup_dir'\n";
1043
print STDERR "$prefix from original InnoDB data directory '$orig_ibdata_dir'\n";
1044
foreach my $a (split(/;/, $orig_innodb_data_file_path)) {
1045
my $path = (split(/:/,$a))[0];
1046
$path=~s/([\$\\\" ])/\\$1/g;
1047
if($option_remote_host) {
1048
print STDERR "$prefix Backing up file '$orig_ibdata_dir/$path'\n";
1049
system("scp $option_scp_opt '$orig_ibdata_dir/$path' '$option_remote_host:$backup_dir/$path'")
1050
and Die "Failed to scp file '$path': $!";
1051
} elsif($option_stream eq 'tar') {
1054
print STDERR "$prefix Backing up as tar stream '$path'\n";
1055
if (!$option_tar4ibd) {
1056
$tarcmd = "tar chf - -b 32";
1058
$tarcmd = "tar4ibd";
1059
if ($innodb_use_odirect) {
1060
$tarcmd = "$tarcmd -d";
1062
$tarcmd = "$tarcmd -c";
1064
$ret = system("cd $orig_ibdata_dir; $tarcmd $path") >> 8;
1066
print STDERR "$prefix If you use GNU tar, this warning can be ignored.\n";
1067
} elsif ($ret != 0) {
1068
print STDERR "$prefix tar returned with exit code $ret.\n";
1069
if ( -e "$orig_ibdata_dir/$path" ) {
1070
Die "Failed to stream '$orig_ibdata_dir/$path': $!";
1073
print STDERR "$prefix Ignoring nonexistent file '$orig_ibdata_dir/$path'.\n";
1080
opendir(DIR, $orig_datadir)
1081
|| Die "Can't open directory '$orig_datadir': $!\n";
1082
while (defined($subdir = readdir(DIR))) {
1083
my $print_each_file = 0;
1086
if ($subdir eq '.' || $subdir eq '..') { next; }
1087
next unless -d "$orig_datadir/$subdir";
1088
next unless check_if_required($subdir);
1090
@list = glob("$orig_datadir/$subdir/" . '*.ibd');
1093
if ($file_c <= $backup_file_print_limit) {
1094
$print_each_file = 1;
1096
print STDERR "$prefix Backing up files " .
1097
"'$orig_datadir/$subdir/*.ibd' ($file_c files)\n";
1099
foreach $file (@list) {
1100
next unless check_if_required($subdir, $file);
1101
if($option_include) {
1104
$table_name = substr($file, rindex($file, '/'));
1105
$table_name = substr($table_name, 1, rindex($table_name, '.') - 1);
1106
$table_name = $subdir . "." . $table_name;
1108
if (!($table_name =~ /$option_include/)) {
1109
print STDERR "'$file' is skipped.\n";
1114
if ($print_each_file) {
1115
print STDERR "$prefix Backing up file '$file'\n";
1117
if($option_remote_host) {
1118
if (system("ssh $option_remote_host test -e $backup_dir/$subdir")
1120
system("ssh $option_remote_host mkdir $backup_dir/$subdir");
1122
system("scp $option_scp_opt '$file' '$option_remote_host:$backup_dir/$subdir/'")
1123
and Die "Failed to scp file '$file': $!";
1124
} elsif($option_stream eq 'tar') {
1126
my $file_name = substr($file, rindex($file, '/') + 1);
1127
$file_name=~s/([\$\\\" ])/\\$1/g;
1128
if (!$option_tar4ibd) {
1129
$ret = system("cd $orig_datadir; tar chf - -b 32 $subdir/$file_name") >> 8;
1131
$ret = system("cd $orig_datadir; tar4ibd -c $subdir/$file_name") >> 8;
1134
print STDERR "$prefix If you use GNU tar, this warning can be ignored.\n";
1135
} elsif ($ret != 0) {
1136
print STDERR "$prefix tar returned with exit code $ret.\n";
1137
if ( -e "$orig_datadir/$subdir/$file_name" ) {
1138
Die "Failed to stream '$orig_datadir/$subdir/$file_name': $!";
1141
print STDERR "$prefix Ignoring nonexistent file '$orig_datadir/$subdir/$file_name'.\n";
1150
if($option_remote_host || $option_stream) {
1151
open(STDOUT, "> $tmp_logfile")
1152
|| Die "Failed to open file '$tmp_logfile': $!"
1156
exec($cmdline) || Die "Failed to exec ibbackup: $!";
1159
Die "failed to fork ibbackup child process: $!";
1165
# get_mysql_options subroutine returns the options to mysql client program
1166
# as a string. The options are determined from the options given by the
1167
# user to innobackup.
1169
sub get_mysql_options {
1172
# this option has to be first
1173
if ($option_defaults_file) {
1174
$options = "$options --defaults-file='$option_defaults_file'";
1177
if ($option_mysql_password) {
1178
$options = "$options --password='$option_mysql_password'";
1180
if ($option_mysql_user) {
1181
$options = "$options --user='$option_mysql_user'";
1183
if ($option_mysql_host) {
1184
$options = "$options --host='$option_mysql_host'";
1186
if ($option_mysql_port) {
1187
$options = "$options --port='$option_mysql_port'";
1189
if ($option_mysql_socket) {
1190
$options = "$options --socket='$option_mysql_socket'";
1192
$options = "$options --unbuffered --";
1198
# mysql_open subroutine starts mysql as a child process with
1199
# a pipe connection.
1202
my $options = get_mysql_options();
1203
# run mysql as a child process with a pipe connection
1204
$now = current_time();
1205
print STDERR "$now $prefix Starting mysql with options: $options\n";
1206
$mysql_pid = open(*MYSQL_WRITER, "| mysql $options >$mysql_stdout 2>$mysql_stderr ") or Die "Failed to spawn mysql child process: $!";
1207
MYSQL_WRITER->autoflush(1);
1208
$now = current_time();
1209
print STDERR "$now $prefix Connected to database with mysql child process (pid=$mysql_pid)\n";
1216
# mysql_check subroutine checks that the connection to mysql child process
1220
my $mysql_pid_copy = $mysql_pid;
1222
# send a dummy query to mysql child process
1224
my $hello_message = "innobackup hello $hello_id";
1225
print MYSQL_WRITER "select '$hello_message';\n"
1226
or Die "Connection to mysql child process failed: $!";
1230
local $SIG{ALRM} = sub { die "alarm clock restart" };
1233
alarm $mysql_response_timeout;
1234
while (index($stdout, $hello_message) < 0) {
1236
if ($mysql_pid && $mysql_pid == waitpid($mysql_pid, &WNOHANG)) {
1237
my $reason = `cat $mysql_stderr`;
1239
die "mysql child process has died: $reason";
1241
$stdout = `cat $mysql_stdout`;
1242
$stderr = `cat $mysql_stderr | grep -v ^Warning`;
1244
# mysql has reported an error, do exit
1245
die "mysql error: $stderr";
1250
if ($@ =~ /alarm clock restart/) {
1251
Die "Connection to mysql child process (pid=$mysql_pid_copy) timedout."
1252
. " (Time limit of $mysql_response_timeout seconds exceeded."
1253
. " You may adjust time limit by editing the value of parameter"
1254
. " \"\$mysql_response_timeout\" in this script.)";
1255
} elsif ($@) { Die $@; }
1257
$mysql_last_access_time = time();
1262
# mysql_keep_alive subroutine tries to keep connection to the mysqld database
1263
# server alive by sending a dummy query when the connection has been idle
1264
# for the specified time.
1266
sub mysql_keep_alive {
1267
if ((time() - $mysql_last_access_time) > $mysql_keep_alive_timeout) {
1268
# too long idle, send a dummy query
1275
# mysql_send subroutine send a request string to mysql child process.
1276
# This subroutine appends a newline character to the request and checks
1277
# that mysqld receives the query.
1279
# request request string
1282
my $request = shift;
1284
$current_mysql_request = $request;
1285
print MYSQL_WRITER "$request\n";
1287
$current_mysql_request = '';
1292
# mysql_close subroutine terminates mysql child process gracefully.
1295
print MYSQL_WRITER "quit\n";
1296
$now = current_time();
1297
print STDERR "$now $prefix Connection to database server closed\n";
1303
# write_binlog_info subroutine retrieves MySQL binlog position and
1304
# saves it in a file. It also prints it to stdout.
1306
sub write_binlog_info {
1308
my @info_lines = ();
1312
# get binlog position
1313
mysql_send "SHOW MASTER STATUS;";
1315
# get "show master status" output lines (2) from mysql output
1316
file_to_array($mysql_stdout, \@lines);
1317
foreach my $line (@lines) {
1318
if ($line =~ m/innobackup hello/) {
1319
# this is a hello message, ignore it
1321
# this is output line from "show master status"
1322
push(@info_lines, $line);
1326
# write binlog info file
1327
if (!defined $info_lines[1]) {
1328
$info_lines[1] = "";
1330
if (!$option_remote_host) {
1331
open(FILE, ">$binlog_info") ||
1332
Die "Failed to open file '$binlog_info': $!";
1334
open(FILE, "| ssh $option_remote_host 'cat > $binlog_info'") ||
1335
Die "Failed to open file '$option_remote_host:$binlog_info': $!";
1337
print FILE "$info_lines[1]\n";
1340
if ($option_stream eq 'tar') {
1341
system("cd $option_tmpdir; tar chf - xtrabackup_binlog_info")
1342
and Die "Failed to stream 'xtrabackup_binlog_info': $!";
1343
unlink $binlog_info || Die "Failed to delete '$binlog_info': $!";
1346
# get the name of the last binlog file and position in it
1347
($filename, $position) = $info_lines[1] =~ /^\s*([^\s]+)\s+(.*)$/;
1349
if (defined $filename && defined $position) {
1350
$mysql_binlog_position = "filename '$filename', position $position";
1352
$mysql_binlog_position = "filename '', position ";
1358
# write_slave_info subroutine retrieves MySQL binlog position of the
1359
# master server in a replication setup and saves it in a file. It
1360
# also saves it in $msql_slave_position variable.
1362
sub write_slave_info {
1369
# get slave status. Use single quotes here, otherwise
1370
# \G is evaluated as a control character.
1371
mysql_send 'SHOW SLAVE STATUS\G;';
1373
# get output of the "show slave status" command from mysql output
1374
# and extract binlog position of the master server
1375
file_to_array($mysql_stdout, \@lines);
1377
$master = $1 if /Master_Host:\s*(\S*)\s*$/;
1378
$filename = $1 if /Master_Log_File:\s*(\S*)\s*$/;
1379
$position = $1 if /Master_Log_Pos:\s*(\S*)\s*$/;
1382
# print slave status to a file
1383
if (!$option_remote_host) {
1384
open(FILE, ">$slave_info") ||
1385
Die "Failed to open file '$slave_info': $!";
1387
open(FILE, "| ssh $option_remote_host 'cat > $slave_info'") ||
1388
Die "Failed to open file '$option_remote_host:$slave_info': $!";
1390
print FILE "CHANGE MASTER TO MASTER_LOG_FILE='$filename', MASTER_LOG_POS=$position\n";
1393
if ($option_stream eq 'tar') {
1394
system("cd $option_tmpdir; tar chf - xtrabackup_slave_info")
1395
and Die "Failed to stream 'xtrabackup_slave_info': $!";
1396
unlink $slave_info || Die "Failed to delete '$slave_info': $!";
1399
$mysql_slave_position = "master host '$master', filename '$filename', position $position";
1404
# mysql_lockall subroutine puts a read lock on all tables in all databases.
1407
$now = current_time();
1408
print STDERR "$now $prefix Starting to lock all tables...\n";
1410
mysql_send "USE mysql;";
1411
# mysql_send "DROP TABLE IF EXISTS ibbackup_binlog_marker;";
1412
# if (compare_versions($mysql_server_version, '4.1.0') == -1) {
1413
# # MySQL server version is 4.0 or older, ENGINE keyword not supported
1414
# mysql_send "CREATE TABLE ibbackup_binlog_marker(a INT) TYPE=INNODB;";
1416
# # MySQL server version is 4.1 or newer, use ENGINE keyword
1417
# mysql_send "CREATE TABLE ibbackup_binlog_marker(a INT) ENGINE=INNODB;";
1419
mysql_send "SET AUTOCOMMIT=0;";
1420
# mysql_send "INSERT INTO ibbackup_binlog_marker VALUES (1);";
1421
if (compare_versions($mysql_server_version, '4.0.22') == 0
1422
|| compare_versions($mysql_server_version, '4.1.7') == 0) {
1423
# MySQL server version is 4.0.22 or 4.1.7
1424
mysql_send "COMMIT;";
1425
mysql_send "FLUSH TABLES WITH READ LOCK;";
1427
# MySQL server version is other than 4.0.22 or 4.1.7
1428
mysql_send "FLUSH TABLES WITH READ LOCK;";
1429
mysql_send "COMMIT;";
1432
write_slave_info if $option_slave_info;
1434
$now = current_time();
1435
print STDERR "$now $prefix All tables locked and flushed to disk\n";
1440
# mysql_unlockall subroutine releases read locks on all tables in all
1443
sub mysql_unlockall {
1444
mysql_send "UNLOCK TABLES;";
1445
# mysql_send "DROP TABLE IF EXISTS ibbackup_binlog_marker;";
1447
$now = current_time();
1448
print STDERR "$now $prefix All tables unlocked\n";
1453
# catch_sigpipe subroutine is a signal handler for SIGPIPE.
1458
if ($mysql_pid && (-1 == ($rcode = waitpid($mysql_pid, &WNOHANG))
1459
|| $rcode == $mysql_pid)) {
1460
my $reason = `cat $mysql_stderr`;
1461
print STDERR "Pipe to mysql child process broken: $reason at";
1462
system("date +'%H:%M:%S'");
1471
# kill_child_processes subroutine kills all child processes of this process.
1473
sub kill_child_processes {
1474
if ($ibbackup_pid) {
1475
kill($kill_signal, $ibbackup_pid);
1480
kill($kill_signal, $mysql_pid);
1487
# require_external subroutine checks that an external program is runnable
1488
# via the shell. This is tested by calling the program with the
1489
# given arguments. It is checked that the program returns 0 and does
1490
# not print anything to stderr. If this check fails, this subroutine exits.
1492
# program pathname of the program file
1493
# args arguments to the program
1494
# pattern a string containing a regular expression for finding
1495
# the program version.
1496
# this pattern should contain a subpattern enclosed
1497
# in parentheses which is matched with the version.
1498
# version_ref a reference to a variable where the program version
1499
# string is returned. Example "2.0-beta2".
1501
sub require_external {
1502
my $program = shift;
1504
my $pattern = shift;
1505
my $version_ref = shift;
1507
my $tmp_stdout = tmpnam();
1508
my $tmp_stderr = tmpnam();
1512
$rcode = system("$program $args >$tmp_stdout 2>$tmp_stderr");
1516
my $stderr = `cat $tmp_stderr | grep -v ^Warning`;
1518
if ($stderr ne '') {
1521
Die "Couldn't run $program: $stderr";
1525
Die "Couldn't run $program: $error";
1529
my $stdout = `cat $tmp_stdout`;
1531
@lines = split(/\n|;/,$stdout);
1532
print STDERR "$prefix Using $lines[0]\n";
1534
# get version string from the first output line of the program
1535
${$version_ref} = '';
1536
if ($lines[0] =~ /$pattern/) {
1537
${$version_ref} = $1;
1542
# compare_versions subroutine compares two GNU-style version strings.
1543
# A GNU-style version string consists of three decimal numbers delimitted
1544
# by dots, and optionally followed by extra attributes.
1545
# Examples: "4.0.1", "4.1.1-alpha-debug".
1547
# str1 a GNU-style version string
1548
# str2 a GNU-style version string
1553
sub compare_versions {
1562
# remove possible extra attributes
1563
($str1, $extra1) = $str1 =~ /^([0-9.]*)(.*)/;
1564
($str2, $extra2) = $str2 =~ /^([0-9.]*)(.*)/;
1566
# split "dotted" decimal number string into an array
1567
@array1 = split('\.', $str1);
1568
@array2 = split('\.', $str2);
1570
# compare in lexicographic order
1571
for ($i = 0; $i <= $#array1 && $i <= $#array2; $i++) {
1572
if ($array1[$i] < $array2[$i]) {
1574
} elsif ($array1[$i] > $array2[$i]) {
1578
if ($#array1 < $#array2) {
1580
} elsif ($#array1 > $#array2) {
1589
# init subroutine initializes global variables and performs some checks on the
1590
# system we are running on.
1593
my $mysql_version = '';
1594
my $ibbackup_version = '';
1597
# print some instructions to the user
1598
if (!$option_apply_log && !$option_copy_back) {
1600
} elsif ($option_copy_back) {
1605
print STDERR "IMPORTANT: Please check that the $run run completes successfully.\n";
1606
print STDERR " At the end of a successful $run run $innobackup_script\n";
1607
print STDERR " prints \"completed OK!\".\n\n";
1609
# check that MySQL client program and InnoDB Hot Backup program
1610
# are runnable via shell
1611
if (!$option_copy_back) {
1612
# we are making a backup or applying log to backup
1613
if (!$option_apply_log) {
1614
# we are making a backup, we need mysql server
1618
# check that we have mysql client program
1619
require_external('mysql', '--version', 'Ver ([^,]+)',
1622
# get mysql server version
1623
my $options = get_mysql_options();
1624
@lines = split('\n',
1625
`mysql $options -e "select \@\@version"`);
1626
$mysql_server_version = $lines[1];
1627
print STDERR "$prefix Using mysql server version $mysql_server_version\n";
1629
#require_external($option_ibbackup_binary, '--license',
1630
# 'version (\S+)', \$ibbackup_version);
1634
&& $ibbackup_version
1635
&& $ibbackup_version le "2.0") {
1636
# --include option was given, but ibbackup is too
1638
Die "--include option was given, but ibbackup is too old"
1639
. " to support it. You must upgrade to InnoDB Hot Backup"
1640
. " v2.0 in order to use --include option.\n";
1644
# set signal handlers
1645
$SIG{PIPE} = \&catch_sigpipe;
1647
# read MySQL options file
1648
#read_config_file($config_file, \%config);
1649
read_config_file(\%config);
1651
if(!$option_tmpdir) {
1652
$option_tmpdir = get_option(\%config, 'mysqld', 'tmpdir');
1655
# get innodb log home directory from options file
1656
#$innodb_log_group_home_dir =
1657
# get_option(\%config, 'mysqld', 'innodb_log_group_home_dir');
1659
if (!$option_apply_log && !$option_copy_back) {
1660
# we are making a backup, create a new backup directory
1661
if (!$option_remote_host) {
1662
$backup_dir = File::Spec->rel2abs(make_backup_dir());
1664
$backup_dir = make_backup_dir();
1666
print STDERR "$prefix Created backup directory $backup_dir\n";
1667
if (!$option_remote_host && !$option_stream) {
1668
$backup_config_file = $backup_dir . '/backup-my.cnf';
1669
$suspend_file = $backup_dir . '/xtrabackup_suspended';
1670
$mysql_stdout = $backup_dir . '/mysql-stdout';
1671
$mysql_stderr = $backup_dir . '/mysql-stderr';
1672
$binlog_info = $backup_dir . '/xtrabackup_binlog_info';
1673
$slave_info = $backup_dir . '/xtrabackup_slave_info';
1675
$suspend_file = get_option(\%config, 'mysqld', 'datadir') . '/xtrabackup_suspended';
1676
$tmp_logfile = $option_tmpdir . '/xtrabackup_logfile';
1677
$mysql_stdout = $option_tmpdir . '/mysql-stdout';
1678
$mysql_stderr = $option_tmpdir . '/mysql-stderr';
1679
if ($option_stream) {
1680
$backup_config_file = $option_tmpdir . '/backup-my.cnf';
1681
$binlog_info = $option_tmpdir . '/xtrabackup_binlog_info';
1682
$slave_info = $option_tmpdir . '/xtrabackup_slave_info';
1684
$backup_config_file = $backup_dir . '/backup-my.cnf';
1685
$binlog_info = $backup_dir . '/xtrabackup_binlog_info';
1686
$slave_info = $backup_dir . '/xtrabackup_slave_info';
1689
write_backup_config_file($backup_config_file);
1690
} elsif ($option_copy_back) {
1691
#$backup_config_file = $backup_dir . '/backup-my.cnf';
1692
#read_config_file($backup_config_file, \%backup_config);
1698
# write_backup_config_file subroutine creates a backup options file for
1699
# ibbackup program. It writes to the file only those options that
1700
# are required by ibbackup.
1702
# filename name for the created options file
1704
sub write_backup_config_file {
1705
my $filename = shift;
1706
my $innodb_data_file_path =
1707
get_option(\%config, 'mysqld', 'innodb_data_file_path');
1708
my $innodb_log_files_in_group =
1709
get_option(\%config, 'mysqld', 'innodb_log_files_in_group');
1710
my $innodb_log_file_size =
1711
get_option(\%config, 'mysqld', 'innodb_log_file_size');
1714
my @array = split(/;/, $innodb_data_file_path);
1715
for (my $i = 0; $i <= $#array; $i++) {
1716
my @tmp = split(/\/+/, $array[$i]);
1717
$array[$i] = $tmp[-1];
1719
$innodb_data_file_path = join(";", @array);
1721
if (!$option_remote_host) {
1722
$root = $backup_dir;
1723
open(FILE, "> $filename") || Die "Failed to open file '$filename': $!";
1725
$root = `ssh $option_remote_host 'cd $backup_dir; pwd'`;
1726
open(FILE, "| ssh $option_remote_host 'cat > $filename'")
1727
|| Die "Failed to open file '$option_remote_host:$filename': $!";
1730
print FILE "# This MySQL options file was generated by $innobackup_script.\n\n" .
1731
"# The MySQL server\n" .
1734
"innodb_data_home_dir=$root\n" .
1735
"innodb_data_file_path=$innodb_data_file_path\n" .
1736
"innodb_log_group_home_dir=$root\n" .
1737
"innodb_log_files_in_group=$innodb_log_files_in_group\n" .
1738
"innodb_log_file_size=$innodb_log_file_size\n";
1741
if ($option_stream) {
1742
my $filename_dir = dirname($filename);
1743
my $filename_name = basename($filename);
1744
if ($option_stream eq 'tar') {
1745
system("cd $filename_dir; tar chf - $filename_name")
1746
and Die "Failed to stream '$filename_name': $!";
1748
unlink $filename || Die "Failed to delete '$filename': $!";
1754
# check_args subroutine checks command line arguments. If there is a problem,
1755
# this subroutine prints error message and exits.
1763
# check the version of the perl we are running
1765
# this perl is prior to 5.6.0 and uses old style version string
1766
my $required_version = $required_perl_version_old_style;
1767
if ($] lt $required_version) {
1768
print STDERR "$prefix Warning: " .
1769
"Your perl is too old! Innobackup requires\n";
1770
print STDERR "$prefix Warning: perl $required_version or newer!\n";
1773
$perl_version = chr($required_perl_version[0])
1774
. chr($required_perl_version[1])
1775
. chr($required_perl_version[2]);
1776
if ($^V lt $perl_version) {
1777
my $version = chr(48 + $required_perl_version[0])
1778
. "." . chr(48 + $required_perl_version[1])
1779
. "." . chr(48 + $required_perl_version[2]);
1780
print STDERR "$prefix Warning: " .
1781
"Your perl is too old! Innobackup requires\n";
1782
print STDERR "$prefix Warning: perl $version or newer!\n";
1787
# no command line arguments
1792
# read command line options
1793
$rcode = GetOptions('compress:i' => \$option_compress,
1794
'help' => \$option_help,
1795
'version' => \$option_version,
1796
'throttle=i' => \$option_throttle,
1797
'sleep=i' => \$option_sleep,
1798
'apply-log' => \$option_apply_log,
1799
'redo-only' => \$option_redo_only,
1800
'copy-back' => \$option_copy_back,
1801
'include=s' => \$option_include,
1802
'databases=s' => \$option_databases,
1803
'tables-file=s', => \$option_tables_file,
1804
'use-memory=s' => \$option_use_memory,
1805
'uncompress' => \$option_uncompress,
1806
'export' => \$option_export,
1807
'password=s' => \$option_mysql_password,
1808
'user=s' => \$option_mysql_user,
1809
'host=s' => \$option_mysql_host,
1810
'port=s' => \$option_mysql_port,
1811
'slave-info' => \$option_slave_info,
1812
'socket=s' => \$option_mysql_socket,
1813
'no-timestamp' => \$option_no_timestamp,
1814
'defaults-file=s' => \$option_defaults_file,
1815
'incremental' => \$option_incremental,
1816
'incremental-basedir=s' => \$option_incremental_basedir,
1817
'incremental-lsn=s' => \$option_incremental_lsn,
1818
'incremental-dir=s' => \$option_incremental_dir,
1819
'extra-lsndir=s' => \$option_extra_lsndir,
1820
'remote-host=s' => \$option_remote_host,
1821
'stream=s' => \$option_stream,
1822
'tmpdir=s' => \$option_tmpdir,
1823
'no-lock' => \$option_no_lock,
1824
'ibbackup=s' => \$option_ibbackup_binary,
1825
'scpopt=s' => \$option_scp_opt,
1826
'force-tar', => \$option_force_tar,
1827
'parallel=i' => \$option_parallel,
1828
'safe-slave-backup' => \$option_safe_slave_backup,
1829
'safe-slave-backup-timeout' => $option_safe_slave_backup_timeout,
1833
# failed to read options
1834
print STDERR "$prefix Bad command line arguments\n";
1839
# print help text and exit
1843
if ($option_version) {
1844
# print program version and copyright
1849
if ($option_compress == 0) {
1850
# compression level no specified, use default level
1851
$option_compress = $default_compression_level;
1854
if ($option_compress == 999) {
1855
# compress option not given in the command line
1856
$option_compress = 0;
1860
print STDERR "$prefix Missing command line argument\n";
1863
} elsif (@ARGV > 1) {
1864
print STDERR "$prefix Too many command line arguments\n";
1869
if ($option_stream) {
1870
if ($option_stream eq 'tar') {
1871
if ( !$option_force_tar ) {
1872
$option_tar4ibd = 'tar4ibd';
1875
print STDERR "Forcing tar instead of tar4ibd\n";
1877
} elsif ($option_stream eq 'tar4ibd') {
1878
$option_stream = 'tar';
1879
$option_tar4ibd = 'tar4ibd';
1880
} elsif ($option_stream eq 'cpio') {
1881
print STDERR "$prefix --stream=cpio is not supported yet\n";
1884
print STDERR "$prefix Unknown option --stream=$option_stream\n";
1889
# get options file name
1890
#$config_file = $ARGV[0];
1892
if (!$option_apply_log && !$option_copy_back) {
1893
# we are making a backup, get backup root directory
1894
$backup_root = $ARGV[0];
1895
if ($option_incremental) {
1896
my @dirs = `ls -1 -t $backup_root`;
1897
my $inc_dir = $dirs[0];
1899
if ($option_incremental_basedir) {
1900
$incremental_basedir = $option_incremental_basedir;
1902
$incremental_basedir = File::Spec->catfile($backup_root, $inc_dir);
1905
#print STDERR "--incremental_basedir=$incremental_basedir\n";
1906
#print STDERR "incremental backup is not supported for now.\n";
1910
# get backup directory
1911
$backup_dir = File::Spec->rel2abs($ARGV[0]);
1916
parse_databases_option_value();
1917
parse_tables_file_option_value($option_tables_file);
1922
# make_backup_dir subroutine creates a new backup directory and returns
1925
sub make_backup_dir {
1927
my $innodb_data_file_path =
1928
get_option(\%config, 'mysqld', 'innodb_data_file_path');
1930
# create backup directory
1931
$dir = $backup_root;
1932
if ($option_stream) {
1936
$dir .= '/' . strftime("%Y-%m-%d_%H-%M-%S", localtime())
1937
unless $option_no_timestamp;
1938
if (!$option_remote_host) {
1939
mkdir($dir, 0777) || Die "Failed to create backup directory $dir: $!";
1941
system("ssh $option_remote_host mkdir $dir");
1944
# create subdirectories for ibdata files if needed
1945
# foreach my $a (split(/;/, $innodb_data_file_path)) {
1946
# my $path = (split(/:/,$a))[0];
1947
# my @relative_path = split(/\/+/, $path);
1948
# pop @relative_path;
1949
# if (@relative_path) {
1950
# # there is a non-trivial path from the backup directory
1951
# # to the directory of this backup ibdata file, check
1952
# # that all the directories in the path exist.
1953
# create_path_if_needed($dir, \@relative_path);
1962
# create_path_if_needed subroutine checks that all components
1963
# in the given relative path are directories. If the
1964
# directories do not exist, they are created.
1966
# root a path to the root directory of the relative pathname
1967
# relative_path a relative pathname (a reference to an array of
1968
# pathname components)
1970
sub create_path_if_needed {
1972
my $relative_path = shift;
1976
foreach $a (@{$relative_path}) {
1977
$path = $path . "/" . $a;
1978
if (!$option_remote_host) {
1980
# this directory does not exist, create it !
1981
mkdir($path, 0777) || Die "Failed to create backup directory: $!";
1984
if (system("ssh $option_remote_host test -d $path") != 0) {
1985
system("ssh $option_remote_host mkdir $path");
1993
# remove_from_array subroutine removes excluded element from the array.
1995
# array_ref a reference to an array of strings
1996
# excluded a string to be excluded from the copy
1998
sub remove_from_array {
1999
my $array_ref = shift;
2000
my $excluded = shift;
2004
foreach my $str (@{$array_ref}) {
2005
if ($str ne $excluded) {
2006
$copy[$size] = $str;
2010
@{$array_ref} = @copy;
2015
# backup_files subroutine copies .frm, .MRG, .MYD and .MYI files to
2019
my $source_dir = get_option(\%config, 'mysqld', 'datadir');
2023
my $wildcard = '*.{frm,MYD,MYI,MRG,TRG,TRN,ARM,ARZ,CSM,CSV,opt,par}';
2025
opendir(DIR, $source_dir)
2026
|| Die "Can't open directory '$source_dir': $!\n";
2027
$now = current_time();
2028
print STDERR "\n$now $prefix Starting to backup .frm, .MRG, .MYD, .MYI,\n";
2029
print STDERR "$prefix .TRG, .TRN, .ARM, .ARZ, .CSM, .CSV and .opt files in\n";
2030
print STDERR "$prefix subdirectories of '$source_dir'\n";
2031
# loop through all database directories
2032
while (defined($database = readdir(DIR))) {
2033
my $print_each_file = 0;
2036
# skip files that are not database directories
2037
if ($database eq '.' || $database eq '..') { next; }
2038
next unless -d "$source_dir/$database";
2039
next unless check_if_required($database);
2041
if (!$option_remote_host && !$option_stream) {
2042
if (! -e "$backup_dir/$database") {
2043
# create database directory for the backup
2044
mkdir("$backup_dir/$database", 0777)
2045
|| Die "Couldn't create directory '$backup_dir/$database': $!";
2047
} elsif ($option_remote_host) {
2048
if (system("ssh $option_remote_host test -e $backup_dir/$database")
2050
system("ssh $option_remote_host mkdir $backup_dir/$database");
2054
# copy files of this database
2055
opendir(DBDIR, "$source_dir/$database");
2056
@list = grep(/\.(frm)|(MYD)|(MYI)|(MRG)|(TRG)|(TRN)|(ARM)|(ARZ)|(CSM)|(CSV)|(opt)|(par)$/, readdir(DBDIR));
2059
if ($file_c <= $backup_file_print_limit) {
2060
$print_each_file = 1;
2062
print STDERR "$prefix Backing up files " .
2063
"'$source_dir/$database/$wildcard' ($file_c files)\n";
2065
foreach $file (@list) {
2066
# copying may take a long time, so we have to prevent
2067
# mysql connection from timing out
2069
next unless check_if_required($database, $file);
2071
if($option_include) {
2072
if (!("$database.$file" =~ /$option_include/)) {
2073
print STDERR "$database.$file is skipped because it does not match $option_include.\n";
2079
if ($print_each_file) {
2080
print STDERR "$prefix Backing up file '$source_dir/$database/$file'\n";
2082
if (!$option_remote_host && !$option_stream) {
2083
$src_name = escape_path("$source_dir/$database/$file");
2084
$dst_name = escape_path("$backup_dir/$database");
2085
system("$CP_CMD \"$src_name\" \"$dst_name\"")
2086
and Die "Failed to copy file '$file': $!";
2087
} elsif ($option_remote_host) {
2088
# Queue up files for one single scp per database.
2089
push(@scp_files, "'$file'");
2090
} elsif($option_stream eq 'tar') {
2092
my $file_name = substr($file, rindex($file, '/') + 1);
2093
$file_name=~s/([\$\\\" ])/\\$1/g;
2094
$ret = system("cd $source_dir; tar cf - $database/$file_name") >> 8;
2096
print STDERR "$prefix If you use GNU tar, this warning can be ignored.\n";
2097
} elsif ($ret != 0) {
2098
print STDERR "$prefix tar returned with exit code $ret.\n";
2099
Die "Failed to stream '$database/$file_name': $!";
2103
if ($option_remote_host and @scp_files) {
2104
my $scp_file_list = join(" ", map { "$source_dir/$database/$_" } @scp_files);
2105
system("scp $option_scp_opt $scp_file_list '$option_remote_host:$backup_dir/$database/'")
2106
and Die "Failed to execute \"scp $option_scp_opt $scp_file_list '$option_remote_host:$backup_dir/$database/'\": $!";
2111
$now = current_time();
2112
print STDERR "$now $prefix Finished backing up .frm, .MRG, .MYD, .MYI, .TRG, .TRN, .ARM, .ARZ, .CSV, .CSM and .opt files\n\n";
2117
# file_to_array subroutine reads the given text file into an array and
2118
# stores each line as an element of the array. The end-of-line
2119
# character(s) are removed from the lines stored in the array.
2121
# filename name of a text file
2122
# lines_ref a reference to an array
2125
my $filename = shift;
2126
my $lines_ref = shift;
2128
open(FILE, $filename) || Die "can't open file '$filename': $!";
2129
@{$lines_ref} = <FILE>;
2130
close(FILE) || Die "can't close file '$filename': $!";
2132
foreach my $a (@{$lines_ref}) {
2139
# unescape_string subroutine expands escape sequences found in the string and
2140
# returns the expanded string. It also removes possible single or double quotes
2145
# a string with expanded escape sequences
2147
sub unescape_string {
2152
# remove quotes around the value if they exist
2153
if (length($value) >= 2) {
2154
if ((substr($value, 0, 1) eq "'" && substr($value, -1, 1) eq "'")
2155
|| (substr($value, 0, 1) eq '"' && substr($value, -1, 1) eq '"')) {
2156
$value = substr($value, 1, -1);
2160
# expand escape sequences
2161
while ($offset < length($value)) {
2162
my $pos = index($value, "\\", $offset);
2164
$pos = length($value);
2165
$result = $result . substr($value, $offset, $pos - $offset);
2168
my $replacement = substr($value, $pos, 2);
2169
my $escape_code = substr($value, $pos + 1, 1);
2170
if (exists $option_value_escapes{$escape_code}) {
2171
$replacement = $option_value_escapes{$escape_code};
2174
. substr($value, $offset, $pos - $offset)
2185
# read_config_file subroutine reads MySQL options file and
2186
# returns the options in a hash containing one hash per group.
2188
# filename name of a MySQL options file
2189
# groups_ref a reference to hash variable where the read
2190
# options are returned
2192
sub read_config_file {
2193
#my $filename = shift;
2194
my $groups_ref = shift;
2203
if ($option_defaults_file) {
2204
$options = $options . " --defaults-file=\"$option_defaults_file\" ";
2207
$options = $options . "--print-param";
2210
# read file to an array, one line per element
2211
#file_to_array($filename, \@lines);
2212
$cmdline = "$option_ibbackup_binary $options";
2213
@lines = `$cmdline`;
2215
# classify lines and save option values
2217
$group_hash_ref = {};
2218
${$groups_ref}{$group} = $group_hash_ref;
2219
# this pattern described an option value which may be
2220
# quoted with single or double quotes. This pattern
2221
# does not work by its own. It assumes that the first
2222
# opening parenthesis in this string is the second opening
2223
# parenthesis in the full pattern.
2224
my $value_pattern = q/((["'])([^\\\4]|(\\[^\4]))*\4)|([^\s]+)/;
2225
for ($i = 0; $i < @lines; $i++) {
2226
SWITCH: for ($lines[$i]) {
2235
if (!exists ${$groups_ref}{$group}) {
2236
$group_hash_ref = {};
2237
${$groups_ref}{$group} = $group_hash_ref;
2239
$group_hash_ref = ${$groups_ref}{$group};
2245
/^\s*([^\s=]+)\s*(#.*)?$/
2247
${$group_hash_ref}{$1} = '';
2251
# set-variable = option = value
2252
/^\s*set-variable\s*=\s*([^\s=]+)\s*=\s*($value_pattern)\s*(#.*)?$/
2253
&& do { ${$group_hash_ref}{$1} = unescape_string($2); last; };
2256
/^\s*([^\s=]+)\s*=\s*($value_pattern)\s*(#.*)?$/
2257
&& do { ${$group_hash_ref}{$1} = unescape_string($2); last; };
2264
print("$prefix: Warning: Ignored unrecognized line ",
2266
" in options : '${lines[$i]}'\n"
2274
# get_option subroutine returns the value of given option in the config
2275
# structure. If option is missing, this subroutine calls exit.
2277
# config_ref a reference to a config data
2278
# group option group name
2279
# option_name name of the option
2281
# option value as a string
2284
my $config_ref = shift;
2286
my $option_name = shift;
2289
if (!exists $config{$group}) {
2291
print STDERR "$prefix fatal error: no '$group' group in MySQL options\n";
2292
print STDERR "$prefix fatal error: OR no 'datadir' option in group '$group' in MySQL options\n";
2296
$group_hash_ref = ${$config_ref}{$group};
2297
if (!exists ${$group_hash_ref}{$option_name}) {
2299
print STDERR "$prefix fatal error: no '$option_name' option in group '$group' in MySQL options\n";
2303
return ${$group_hash_ref}{$option_name};
2306
# check_if_required subroutine returns 1 if the specified database and
2307
# table needs to be backed up.
2309
# $_[0] name of database to be checked
2310
# $_[1] full path of table file (This argument is optional)
2312
# 1 if backup should be done and 0 if not
2314
sub check_if_required {
2315
my ( $db, $table_path ) = @_;
2316
my $db_count = scalar keys %databases_list;
2317
my $tbl_count = scalar keys %table_list;
2321
if ( $db_count == 0 && $tbl_count == 0 ) {
2322
# No databases defined with --databases option, include all databases,
2323
# and no tables defined with --tables-file option, include all tables.
2327
if ( $table_path ) {
2328
# get the last component in the table pathname
2329
$filename = (reverse(split(/\//, $table_path)))[0];
2330
# get name of the table by removing file suffix
2331
$table = (split(/\./, $filename))[0];
2335
# Filter for --databases.
2337
if (defined $databases_list{$db}) {
2338
if (defined $table_path) {
2339
my $db_hash = $databases_list{$db};
2340
$db_count = keys %$db_hash;
2341
if ($db_count > 0 && ! defined $databases_list{$db}->{$table}) {
2342
# --databases option specified, but table is not included
2346
# include this database and table
2350
# --databases option given, but database is not included
2355
# Filter for --tables-file.
2357
return 0 unless exists $table_list{$db};
2358
return 0 if $table && !$table_list{$db}->{$table};
2361
return 1; # backup the table
2365
# parse_databases_option_value subroutine parses the value of
2366
# --databases option. If the option value begins with a slash
2367
# it is considered a pathname and the option value is read
2370
# This subroutine sets the global "databases_list" variable.
2372
sub parse_databases_option_value {
2375
if ($option_databases =~ /^\//) {
2376
# the value of the --databases option begins with a slash,
2377
# the option value is pathname of the file containing
2379
if (! -f $option_databases) {
2380
Die "can't find file '$option_databases'";
2383
# read from file the value of --databases option
2385
file_to_array($option_databases, \@lines);
2386
$option_databases = join(" ", @lines);
2389
# mark each database or database.table definition in the
2390
# global databases_list.
2391
foreach $item (split(/\s/, $option_databases)) {
2397
# ignore empty strings
2401
# get database and table names
2402
if ($item =~ /(\S*)\.(\S*)/) {
2403
# item is of the form DATABASE.TABLE
2407
# item is database name, table is undefined
2411
if (! defined $databases_list{$db}) {
2412
# create empty hash for the database
2413
$databases_list{$db} = \%hash;
2416
# add mapping table --> 1 to the database hash
2417
my $h = $databases_list{$db};
2423
# Parse the --tables-file file to determine which InnoDB tables
2424
# are backedup up. Only backedup tables have their .frm, etc.
2426
sub parse_tables_file_option_value {
2427
my ( $filename ) = @_;
2429
return unless $filename;
2431
open my $fh, '<', $filename;
2433
while ( my $line = <$fh> ) {
2435
my ( $db, $tbl ) = $line =~ m/\s*([^\.]+)\.([^\.]+)\s*/;
2436
if ( $db && $tbl ) {
2437
$table_list{$db}->{$tbl} = 1;
2438
print STDERR "$prefix $db.$tbl will be registerd to the list\n";
2441
warn "$prefix Invalid line in $filename: $line";
2446
warn "$prefix Cannot read --tables-file $filename: $OS_ERROR";
2456
$str =~ s/\\\\/\\/g;
2459
$str =~ s/\/\//\//g;
2465
sub set_xtrabackup_version {
2466
# Based on MySQL version choose correct binary
2467
# MySQL 5.0.* - xtrabackup_51
2468
# MySQL 5.1.* - xtrabackup_51
2469
# MySQL 5.1.* with InnoDB plugin - xtrabackup
2470
# Percona Server >= 11.0 - xtrabackup
2471
# MySQL 5.5.* - xtrabackup_55
2474
my $var_version = '';
2475
my $var_innodb_version = '';
2476
my $ibbackup_binary;
2478
mysql_send "SHOW VARIABLES LIKE 'version'\\G";
2479
file_to_array($mysql_stdout, \@lines);
2481
$var_version = $1 if /Value:\s+(\S+)/;
2483
mysql_send "SHOW VARIABLES LIKE 'innodb_version'\\G";
2484
file_to_array($mysql_stdout, \@lines);
2486
$var_innodb_version = $1 if /Value:\s+(\S+)/;
2488
if($var_version =~ m/5\.0\.\d/){
2489
$ibbackup_binary = ($win eq 1 ? 'xtrabackup.exe' : 'xtrabackup_51');
2491
if($var_version =~ m/5\.1\.\d/ and $var_innodb_version =~ m//){
2492
$ibbackup_binary = ($win eq 1 ? 'xtrabackup.exe' : 'xtrabackup_51');
2494
if($var_version =~ m/5\.1\.\d/ and $var_innodb_version =~ m/1\.0\.\d+$/){
2495
$ibbackup_binary = ($win eq 1 ? 'xtrabackup.exe' : 'xtrabackup');
2497
if($var_version =~ m/5\.1\.\d/ and $var_innodb_version =~ m/1\.0\.\d+-\d/){
2498
$ibbackup_binary = ($win eq 1 ? 'xtrabackup.exe' : 'xtrabackup');
2500
if($var_version =~ m/5\.5\.\d/){
2501
$ibbackup_binary = ($win eq 1 ? 'xtrabackup.exe' : 'xtrabackup_55');
2504
return $ibbackup_binary;
2507
# Wait until it's safe to backup a slave. Returns immediately if
2508
# the host isn't a slave. Currently there's only one check:
2509
# Slave_open_temp_tables has to be zero. Dies on timeout.
2510
sub wait_for_safe_slave {
2513
my $host_is_slave = 0;
2514
mysql_send 'SHOW SLAVE STATUS\G;';
2515
file_to_array($mysql_stdout, \@lines);
2516
foreach my $line ( @lines ) {
2517
if ( $line =~ m/Read_Master_Log_Pos/ ) {
2522
if ( !$host_is_slave ) {
2523
print STDERR "$prefix: Not checking slave open temp tables for --safe-slave-backup because host is not a slave\n";
2527
mysql_send 'STOP SLAVE SQL_THREAD;';
2529
my $open_temp_tables = get_slave_open_temp_tables();
2530
print STDERR "$prefix: Slave open temp tables: $open_temp_tables\n";
2532
return if $open_temp_tables == 0;
2535
my $n_attempts = int($option_safe_slave_backup_timeout / $sleep_time) || 1;
2536
while ( $n_attempts-- ) {
2537
print STDERR "$prefix: Starting slave SQL thread, waiting $sleep_time seconds, then checking Slave_open_temp_tables again ($n_attempts attempts remaining)...\n";
2539
mysql_send 'START SLAVE SQL_THREAD;';
2541
mysql_send 'STOP SLAVE SQL_THREAD;';
2543
$open_temp_tables = get_slave_open_temp_tables();
2544
print STDERR "$prefix: Slave open temp tables: $open_temp_tables\n";
2545
if ( !$open_temp_tables ) {
2546
print STDERR "$prefix: Slave is safe to backup\n";
2551
Die "Slave_open_temp_tables did not become zero after waiting $option_safe_slave_backup_timeout seconds";
2554
sub get_slave_open_temp_tables {
2556
mysql_send 'SHOW STATUS LIKE "slave_open_temp_tables"\G;';
2557
file_to_array($mysql_stdout, \@lines);
2559
for my $i ( 0..$#lines ) {
2560
$last_value = $i + 1
2561
if $lines[$i] =~ m/Variable_name: Slave_open_temp_tables/i;
2563
Die "SHOW STATUS LIKE 'slave_open_temp_tables' did not return anything"
2566
Die "Failed to get Slave_open_temp_tables from SHOW STATUS"
2567
unless defined $lines[$last_value];
2569
my ($n) = $lines[$last_value] =~ m/(\d+)/;