1088
# get_mysql_options subroutine returns the options to mysql client program
1089
# as a string. The options are determined from the options given by the
1090
# user to innobackup.
1064
# parse_connection_options() subroutine parses connection-related command line
1092
sub get_mysql_options {
1067
sub parse_connection_options {
1070
$con->{dsn} = 'dbi:mysql:';
1095
1072
# this option has to be first
1096
1073
if ($option_defaults_file) {
1097
$options = "$options --defaults-file='$option_defaults_file'";
1074
$con->{dsn} .= ";mysql_read_default_file=$option_defaults_file";
1100
1077
if ($option_defaults_extra_file) {
1101
$options = $options . " --defaults-extra-file=\"$option_defaults_extra_file\" ";
1078
$con->{dsn} .= ";mysql_read_default_file=$option_defaults_extra_file";
1081
$con->{dsn} .= ";mysql_read_default_group=xtrabackup";
1104
1083
if ($option_mysql_password) {
1105
$options = "$options --password='$option_mysql_password'";
1084
$con->{dsn_password} = "$option_mysql_password";
1107
1086
if ($option_mysql_user) {
1108
$options = "$options --user='$option_mysql_user'";
1087
$con->{dsn_user} = "$option_mysql_user";
1110
1089
if ($option_mysql_host) {
1111
$options = "$options --host='$option_mysql_host'";
1090
$con->{dsn} .= ";host=$option_mysql_host";
1113
1092
if ($option_mysql_port) {
1114
$options = "$options --port='$option_mysql_port'";
1093
$con->{dsn} .= ";port=$option_mysql_port";
1116
1095
if ($option_mysql_socket) {
1117
$options = "$options --socket='$option_mysql_socket'";
1119
$options = "$options --unbuffered --";
1125
# Check that the server is responding to queries
1128
my $alarm_handler = shift;
1129
my $mysql_pid_copy = $mysql_pid;
1131
# send a dummy query to mysql child process
1134
my $hello_message = "xtrabackup ping $hello_id";
1135
print MYSQL_WRITER "select '$hello_message';\n"
1136
or Die "Connection to mysql child process failed: $!";
1138
# Don't check server's response if running in a signal handler
1139
# because that breaks system() calls
1146
local $SIG{ALRM} = sub { die "alarm clock restart" };
1149
alarm $mysql_response_timeout;
1150
while (index($stdout, $hello_message) < 0) {
1152
if ($mysql_pid && $mysql_pid == waitpid($mysql_pid, &WNOHANG)) {
1153
my $reason = `cat $mysql_stderr`;
1155
die "mysql child process has died: $reason";
1157
$stdout = `cat $mysql_stdout`;
1158
$stderr = `cat $mysql_stderr | grep -v ^Warning`;
1160
# mysql has reported an error, do exit
1161
die "mysql error: $stderr";
1166
if ($@ =~ /alarm clock restart/) {
1167
Die "Connection to mysql child process (pid=$mysql_pid_copy) timedout."
1168
. " (Time limit of $mysql_response_timeout seconds exceeded."
1169
. " You may adjust time limit by editing the value of parameter"
1170
. " \"\$mysql_response_timeout\" in this script.)";
1171
} elsif ($@) { Die $@; }
1176
# SIGALRM handler which sends a keepalive query to the server
1180
# Reschedule SIGALRM
1181
alarm $mysql_keep_alive;
1186
# Schedule periodic server pings
1096
$con->{dsn} .= ";mysql_socket=$option_mysql_socket";
1101
# Start a background process that will send keep-alive queries periodically
1102
# using the connection passed as a 'mysql' hash reference
1188
1104
sub start_keepalives {
1189
$SIG{ALRM} = \&catch_sigalrm;
1190
alarm $mysql_keep_alive;
1107
if (defined($con->{keep_alive_pid})) {
1108
Die "Keep-alive process has already been started for this connection."
1111
my $keep_alive_pid = fork();
1113
if ($keep_alive_pid) {
1115
$con->{keep_alive_pid} = $keep_alive_pid;
1121
$con->{dbh}->{InactiveDestroy} = 1;
1126
# send dummy queries to connection until interrupted with SIGINT or a
1129
sleep $mysql_keep_alive;
1131
my $hello_message = "xtrabackup ping " . $hello_id++;
1134
$con->{dbh}->selectrow_array("select '$hello_message'");
1194
# Cancel periodic server pings
1146
# Stop the background keep-alive process
1196
1148
sub stop_keepalives {
1198
$SIG{ALRM} = "DEFAULT";
1202
# mysql_open subroutine starts mysql as a child process with
1203
# a pipe connection.
1206
my $options = get_mysql_options();
1207
# run mysql as a child process with a pipe connection
1208
$now = current_time();
1209
(my $prt_options = $options) =~ s/--password=[^ ]+ /--password=xxxxxxxx /g;
1210
print STDERR "$now $prefix Starting mysql with options: $prt_options\n";
1211
$mysql_pid = open(*MYSQL_WRITER, "| mysql $options >$mysql_stdout 2>$mysql_stderr ") or Die "Failed to spawn mysql child process: $!";
1212
MYSQL_WRITER->autoflush(1);
1213
$now = current_time();
1214
print STDERR "$now $prefix Connected to database with mysql child process (pid=$mysql_pid)\n";
1215
print MYSQL_WRITER "SET SESSION wait_timeout = 2147000;\n" or die "Connection to mysql child process failed: $!";
1224
# mysql_send subroutine send a request string to mysql child process.
1225
# This subroutine appends a newline character to the request and checks
1226
# that mysqld receives the query.
1151
if (!defined($con->{keep_alive_pid})) {
1152
Die "Keep-alive process has never been started for this connection."
1155
kill 'INT', $con->{keep_alive_pid};
1156
waitpid($con->{keep_alive_pid}, 0);
1160
Die "Keep-alive process died with exit code " . $rc;
1162
undef $con->{keep_alive_pid};
1166
# mysql_connect subroutine connects to MySQL server
1172
abort_on_error => 1,
1177
$con{abort_on_error} = $args{abort_on_error};
1178
$con{keepalives} = $args{keepalives};
1180
parse_connection_options(\%con);
1182
$now = current_time();
1183
print STDERR "$now $prefix Connecting to MySQL server with DSN '" .
1184
$con{dsn} . "' as '" . $con{dsn_user} . "' (using password: ";
1185
if (defined($con{dsn_password})) {
1186
print STDERR "YES).\n";
1188
print STDERR "NO).\n";
1192
$con{dbh}=DBI->connect($con{dsn}, $con{dsn_user},
1193
$con{dsn_password}, { RaiseError => 1 });
1197
$con{connect_error}=$EVAL_ERROR;
1199
$now = current_time();
1200
print STDERR "$now $prefix Connected to MySQL server\n";
1203
if ($args{abort_on_error}) {
1204
if (!$dbd_mysql_installed) {
1205
die "ERROR: Failed to connect to MySQL server as " .
1206
"DBD::mysql module is not installed";
1209
die "ERROR: Failed to connect to MySQL server: " .
1210
$con{connect_error};
1215
if ($con{dbh} && $con{keepalives}) {
1216
start_keepalives(\%con);
1223
# mysql_query subroutine send a query to MySQL server child process.
1228
# request request string
1231
my $request = shift;
1235
$current_mysql_request = $request;
1236
print MYSQL_WRITER "$request\n";
1238
$current_mysql_request = '';
1245
# mysql_close subroutine terminates mysql child process gracefully.
1225
# query query to execute
1228
my ($con, $query) = @_;
1231
if ($con->{keepalives}) {
1232
stop_keepalives($con);
1235
if ($query eq 'SHOW VARIABLES') {
1236
$con->{vars} = $con->{dbh}->selectall_hashref('SHOW VARIABLES',
1238
} elsif ($query eq 'SHOW STATUS') {
1239
$con->{status} = $con->{dbh}->selectall_hashref('SHOW STATUS',
1241
} elsif ($query eq 'SHOW MASTER STATUS') {
1242
$con->{master_status} =
1243
$con->{dbh}->selectrow_hashref("SHOW MASTER STATUS");
1244
} elsif ($query eq 'SHOW SLAVE STATUS') {
1245
$con->{slave_status} =
1246
$con->{dbh}->selectrow_hashref("SHOW SLAVE STATUS");
1248
$con->{dbh}->do($query);
1251
if ($con->{keepalives}) {
1252
start_keepalives($con);
1256
Die "\nError executing '$query': $EVAL_ERROR\n";
1261
sub get_mysql_vars {
1262
mysql_query($_[0], 'SHOW VARIABLES')
1265
sub get_mysql_status {
1266
mysql_query($_[0], 'SHOW STATUS');
1269
sub get_mysql_master_status {
1270
mysql_query($_[0], "SHOW MASTER STATUS");
1273
sub get_mysql_slave_status {
1274
mysql_query($_[0], "SHOW SLAVE STATUS");
1278
# mysql_close subroutine closes connection to MySQL server gracefully.
1247
1280
sub mysql_close {
1250
print MYSQL_WRITER "quit\n";
1283
if ($con->{keepalives}) {
1284
stop_keepalives($con);
1287
$con->{dbh}->disconnect();
1251
1289
$now = current_time();
1252
1290
print STDERR "$now $prefix Connection to database server closed\n";
1258
1294
# write_binlog_info subroutine retrieves MySQL binlog position and
1259
1295
# saves it in a file. It also prints it to stdout.
1261
1297
sub write_binlog_info {
1266
1300
# get binlog position
1267
mysql_send 'SHOW MASTER STATUS\G';
1301
get_mysql_master_status($con);
1269
1303
# get the name of the last binlog file and position in it
1270
1304
# from the SHOW MASTER STATUS output
1271
file_to_array($mysql_stdout, \@lines);
1273
$filename = $1 if /^\s+File:\s(\S+)\s*$/;
1274
$position = $1 if /^\s+Position:\s(\d+)\s*$/;
1305
my $filename = $con->{master_status}->{File};
1306
my $position = $con->{master_status}->{Position};
1277
1308
# write binlog info file
1278
1309
open(FILE, ">$binlog_info") || Die "Failed to open file '$binlog_info': $!";
2543
2513
sub set_xtrabackup_version {
2544
# Based on MySQL version choose correct binary
2545
# MySQL 5.1.* with InnoDB plugin - xtrabackup
2546
# MariaDB 5.1.* - xtrabackup
2547
# MariaDB 5.2.* - xtrabackup
2548
# MariaDB 5.3.* - xtrabackup
2549
# Percona Server 5.0 - xtrabackup_51
2550
# Percona Server 5.1 - xtrabackup
2551
# Percona Server 5.5 - xtrabackup_55
2552
# MySQL 5.5.* - xtrabackup_55
2553
# MariaDB 5.5.* - xtrabackup_55
2556
my $var_version = '';
2557
my $var_innodb_version = '';
2558
my $ibbackup_binary;
2560
mysql_send "SHOW VARIABLES LIKE 'version'\\G";
2561
file_to_array($mysql_stdout, \@lines);
2563
$var_version = $1 if /Value:\s+(\S+)/;
2565
mysql_send "SHOW VARIABLES LIKE 'innodb_version'\\G";
2566
file_to_array($mysql_stdout, \@lines);
2568
$var_innodb_version = $1 if /Value:\s+(\S+)/;
2570
if($var_version =~ m/5\.0\.\d/){
2514
# Based on MySQL version choose correct binary
2515
# MySQL 5.1.* with InnoDB plugin - xtrabackup
2516
# MariaDB 5.1.* - xtrabackup
2517
# MariaDB 5.2.* - xtrabackup
2518
# MariaDB 5.3.* - xtrabackup
2519
# Percona Server 5.0 - xtrabackup_51
2520
# Percona Server 5.1 - xtrabackup
2521
# Percona Server 5.5 - xtrabackup_55
2522
# MySQL 5.5.* - xtrabackup_55
2523
# MariaDB 5.5.* - xtrabackup_55
2525
my $var_version = '';
2526
my $var_innodb_version = '';
2527
my $ibbackup_binary;
2529
get_mysql_vars(\%mysql);
2531
$var_version = $mysql{vars}->{version}->{Value};
2532
$var_innodb_version = $mysql{vars}->{innodb_version}->{Value};
2535
if($var_version =~ m/5\.0\.\d/) {
2571
2536
Die "MySQL 5.0 support was removed in Percona XtraBackup 2.1. The last version to support MySQL 5.0 was Percona XtraBackup 2.0.";
2573
if($var_version =~ m/5\.1\.\d/ and $var_innodb_version =~ m/.*/){
2539
if($var_version =~ m/5\.1\.\d/ && $var_innodb_version =~ m/.*/) {
2574
2540
Die "Support for MySQL 5.1 with builtin InnoDB (not the plugin) was removed in Percona XtraBackup 2.1. The last version to support MySQL 5.1 with builtin InnoDB was Percona XtraBackup 2.0.";
2576
if($var_version =~ m/5\.1\.\d/ and $var_innodb_version =~ m/1\.0\.\d+$/){
2577
$ibbackup_binary = ($win eq 1 ? 'xtrabackup.exe' : 'xtrabackup');
2579
if($var_version =~ m/5\.1\.\d/ and $var_innodb_version =~ m/1\.0\.\d+-(rel)?\d/){
2580
$ibbackup_binary = ($win eq 1 ? 'xtrabackup.exe' : 'xtrabackup');
2582
if($var_version =~ m/5\.2\.\d/){
2583
$ibbackup_binary = ($win eq 1 ? 'xtrabackup.exe' : 'xtrabackup');
2585
if($var_version =~ m/5\.3\.\d/){
2586
$ibbackup_binary = ($win eq 1 ? 'xtrabackup.exe' : 'xtrabackup');
2588
if($var_version =~ m/5\.5\.\d/){
2543
if($var_version =~ m/5\.1\.\d/ && $var_innodb_version =~ m/1\.0\.\d+$/) {
2544
$ibbackup_binary = ($win eq 1 ? 'xtrabackup.exe' : 'xtrabackup');
2547
if($var_version =~ m/5\.1\.\d/ && $var_innodb_version =~ m/1\.0\.\d+-(rel)?\d/){
2548
$ibbackup_binary = ($win eq 1 ? 'xtrabackup.exe' : 'xtrabackup');
2551
if($var_version =~ m/5\.2\.\d/){
2552
$ibbackup_binary = ($win eq 1 ? 'xtrabackup.exe' : 'xtrabackup');
2555
if($var_version =~ m/5\.3\.\d/){
2556
$ibbackup_binary = ($win eq 1 ? 'xtrabackup.exe' : 'xtrabackup');
2559
if($var_version =~ m/5\.5\.\d/){
2589
2560
$ibbackup_binary = ($win eq 1 ? 'xtrabackup.exe' : 'xtrabackup_55');
2592
return $ibbackup_binary;
2563
return $ibbackup_binary;
2595
2566
# Wait until it's safe to backup a slave. Returns immediately if
2596
2567
# the host isn't a slave. Currently there's only one check:
2597
2568
# Slave_open_temp_tables has to be zero. Dies on timeout.
2598
2569
sub wait_for_safe_slave {
2600
2573
# whether host is detected as slave in safe slave backup mode
2601
2574
my $host_is_slave = 0;
2603
2576
$sql_thread_started = 0;
2577
get_mysql_slave_status($con);
2605
mysql_send 'SHOW SLAVE STATUS\G;';
2606
file_to_array($mysql_stdout, \@lines);
2607
foreach my $line ( @lines ) {
2608
if ( $line =~ m/Read_Master_Log_Pos/ ) {
2579
if (defined($con->{slave_status}->{Read_Master_Log_Pos})) {
2609
2580
$host_is_slave = 1;
2610
} elsif ( $line =~ m/Slave_SQL_Running:.*Yes/ ) {
2583
if ($con->{slave_status}->{Slave_SQL_Running} =~ m/Yes/ ) {
2611
2584
$sql_thread_started = 1;
2614
2587
if ( !$host_is_slave ) {
2615
2588
print STDERR "$prefix: Not checking slave open temp tables for --safe-slave-backup because host is not a slave\n";
2619
2592
if ($sql_thread_started) {
2620
mysql_send 'STOP SLAVE SQL_THREAD;';
2593
mysql_query($con, 'STOP SLAVE SQL_THREAD');
2623
my $open_temp_tables = get_slave_open_temp_tables();
2596
my $open_temp_tables = get_slave_open_temp_tables($con);
2624
2597
print STDERR "$prefix: Slave open temp tables: $open_temp_tables\n";
2626
2599
return if $open_temp_tables == 0;