--- innobackupex.orig 2014-06-05 11:49:12.523955742 -0400 +++ innobackupex 2014-06-13 10:32:15.915620008 -0400 @@ -272,6 +272,8 @@ my $copy_dir_overwrite; my $copy_dir_resolve_isl; +my %gtid; + # ########################################################################### # HTTPMicro package # This package is a copy without comments from the original. The original @@ -3052,11 +3054,80 @@ } # +# Initialize the gtid state from the MySQL/MariaDB server. +# +# MySQL specific variables: +# *) gtid_executed_master (retreived from SHOW MASTER STATUS) +# *) gtid_executed_slave (retreived from SHOW SLAVE STATUS) +# *) gtid_purged +# +# MariaDB specific variables: +# *) gtid_binlog_pos +# *) gtid_current_pos +# *) gtid_slave_pos +# *) gtid_binlog_state +# +sub init_gtid_state { + my $con = shift; + my $mysql_server_version; + + # get master status + get_mysql_master_status($con); + if (defined($con->{master_status}->{Executed_Gtid_Set})) { + $gtid{'gtid_executed_master'} = $con->{master_status}->{Executed_Gtid_Set} || ''; + } + + # get slave status + get_mysql_slave_status($con); + if (defined($con->{slave_status}->{Executed_Gtid_Set})) { + $gtid{'gtid_executed_slave'} = $con->{slave_status}->{Executed_Gtid_Set} || ''; + } + + if (defined($con->{vars}->{gtid_purged})) { # Introduced in MySQL-5.6.9 + $gtid{'gtid_purged'} = $con->{vars}->{gtid_purged} || ''; + } + + # MariaDB variables + if (defined($con->{vars}->{gtid_binlog_pos})) { # Introduced in MariaDB-10.0.3 + $gtid{'gtid_binlog_pos'} = $con->{vars}->{gtid_binlog_pos}->{Value} || ''; + } + if (defined($con->{vars}->{gtid_current_pos})) { # Introduced in MariaDB-10.0.3 + $gtid{'gtid_current_pos'} = $con->{vars}->{gtid_current_pos}->{Value} || ''; + } + + if (defined($con->{vars}->{gtid_slave_pos})) { # Introduced in MariaDB-10.0.3 + $gtid{'gtid_slave_pos'}= $con->{vars}->{gtid_slave_pos}->{Value} || ''; + } + + if (defined($con->{vars}->{gtid_binlog_state})) { # Introduced in MariaDB-10.0.5 + $gtid{'gtid_binlog_state'} = $con->{vars}->{gtid_binlog_state}->{Value} || ''; + } +} + +sub append_gtid_variables { + my $gtids = ''; + my $count = keys %gtid; + + foreach my $key ( keys %gtid ) + { + $count --; + $gtids .= " "; + $gtids .= ($key . " "); # append key + $gtids .= ($gtid{$key} ne '') ? $gtid{$key} : "#"; # append value (or #) + $gtids .= ($count > 0) ? "," : ""; + } + + return $gtids; +} + +# # write_binlog_info subroutine retrieves MySQL binlog position and # saves it in a file. It also prints it to stdout. # sub write_binlog_info { my $con = shift; + my $_gtid = ''; + my $gtid_impl = 0; # get binlog position get_mysql_master_status($con); @@ -3065,7 +3136,13 @@ # from the SHOW MASTER STATUS output my $filename = $con->{master_status}->{File}; my $position = $con->{master_status}->{Position}; - my $gtid = $con->{master_status}->{Executed_Gtid_Set} || ''; + if (defined($gtid{'gtid_executed_master'})) { + $_gtid = $gtid{'gtid_executed_master'}; + $gtid_impl = 1; + } elsif (defined($gtid{'gtid_current_pos'})) { + $_gtid = $gtid{'gtid_current_pos'}; + $gtid_impl = 2; + } # Do not create xtrabackup_binlog_info if binary log is disabled if (!defined($filename) or !defined($position)) { @@ -3073,11 +3150,16 @@ } # write binlog info file - write_to_backup_file("$binlog_info", "$filename\t$position\t\t$gtid\n"); + write_to_backup_file("$binlog_info", "$filename\t$position\t\t$_gtid\n"); $mysql_binlog_position = "filename '$filename', position $position"; - if ($gtid) { - $mysql_binlog_position .= ", gtid_executed $gtid"; + + if ($gtid_impl == 1) { + # MySQL-5.6 + $mysql_binlog_position .= ", gtid_executed $_gtid"; + } elsif ($gtid_impl == 2) { + # MariaDB-10.0 + $mysql_binlog_position .= (", " . append_gtid_variables()); } } @@ -3091,6 +3173,7 @@ my @info_lines = (); my $state_uuid = ''; my $last_committed = ''; + my $gtid_exists= 0; # get binlog position get_mysql_status($con); @@ -3112,13 +3195,15 @@ write_to_backup_file("$galera_info", "$state_uuid" . ":" . "$last_committed" . "\n"); - if (!defined($con->{master_status})) { - get_mysql_master_status($con); + # Determine if GTIDs exist. + if (defined($gtid{'gtid_executed_master'})) { # >= MySQL-5.6 + $gtid_exists= 1; + } elsif (defined($gtid{'gtid_binlog_state'}) && # >= MariaDB-10.0 + ($gtid{'gtid_binlog_state'} ne '')) { + $gtid_exists= 1; } - my $gtid = $con->{master_status}->{Executed_Gtid_Set} || ''; - - if ($gtid) { + if ($gtid_exists) { my $log_bin_dir; my $log_bin_file; @@ -3126,7 +3211,13 @@ get_mysql_master_status($con); $log_bin_file = $con->{master_status}->{File}; - $log_bin_dir = File::Basename::dirname($mysql{vars}->{log_bin_basename}->{Value}); + + if (defined($mysql{vars}->{log_bin_basename})) { # >= MySQL-5.6 + # sysvar.log_bin_basename does not exist in MariaDB + $log_bin_dir = File::Basename::dirname($mysql{vars}->{log_bin_basename}->{Value}); + } else { # fallback to datadir + $log_bin_dir = $mysql{vars}->{datadir}->{Value}; + } if (!defined($log_bin_file) || !defined($log_bin_dir)) { die "Failed to get master binlog coordinates from SHOW MASTER STATUS"; @@ -3149,15 +3240,11 @@ my @lines; my @info_lines; - # get slave status - get_mysql_slave_status($con); - # get output of the "show slave status" command from mysql output # and extract binlog position of the master server my $master = $con->{slave_status}->{Master_Host}; my $filename = $con->{slave_status}->{Relay_Master_Log_File}; my $position = $con->{slave_status}->{Exec_Master_Log_Pos}; - my $gtid_executed = $con->{slave_status}->{Executed_Gtid_Set}; if (!defined($master) || !defined($filename) || !defined($position)) { my $now = current_time(); @@ -3173,13 +3260,24 @@ # Print slave status to a file. # If GTID mode is used, construct a CHANGE MASTER statement with # MASTER_AUTO_POSITION and correct a gtid_purged value. - if (defined($gtid_executed) && $gtid_executed) { + if (defined($gtid{'gtid_executed_slave'}) && + ($gtid{'gtid_executed_slave'} ne '')) { + my $gtid_executed= $gtid{'gtid_executed_slave'}; $gtid_executed =~ s/\n/ /; - write_to_backup_file("$slave_info", + write_to_backup_file("$slave_info", "SET GLOBAL gtid_purged='$gtid_executed';\n" . - "CHANGE MASTER TO MASTER_AUTO_POSITION=1\n"); + "CHANGE MASTER TO MASTER_AUTO_POSITION=1;\n"); $mysql_slave_position = "master host '$master', ". "purge list '$gtid_executed'"; + } elsif (defined($gtid{'gtid_current_pos'})) { + write_to_backup_file("$slave_info", + "CHANGE MASTER TO master_use_gtid = " . + "slave_pos\n"); # or current_pos ?? + + $mysql_slave_position = "master host '$master', "; + # append GTID variables + $mysql_slave_position .= append_gtid_variables(); + } else { write_to_backup_file("$slave_info", "CHANGE MASTER TO MASTER_LOG_FILE='$filename', " . @@ -3550,6 +3648,10 @@ if (!$option_apply_log) { # we are making a backup, we need mysql server get_mysql_vars(\%mysql); + + # initialize gtid state + init_gtid_state(\%mysql); + $mysql_server_version = $mysql{vars}->{version}->{Value}; print STDERR "$prefix Using mysql server version $mysql_server_version\n"; }