From 8cbb5a0c8f4826478bbdfd485a73670c41d7d308 Mon Sep 17 00:00:00 2001 From: Sveta Smirnova Date: Thu, 25 Jul 2024 23:37:22 +0300 Subject: [PATCH] PT-2340 - Support MySQL 8.4 - Removed lib/Percona/Test.pm, lib/Safeguards.pm, t/lib/Safeguards.t, because they are not used anymore - Removed word "slave" from lib --- bin/pt-table-checksum | 20 +- bin/pt-variable-advisor | 25 + lib/Cxn.pm | 6 +- lib/MasterSlave.pm | 463 +++++++++--------- lib/MySQLConfig.pm | 2 +- lib/MySQLProtocolParser.pm | 4 +- lib/Percona/Test.pm | 814 -------------------------------- lib/Percona/XtraDB/Cluster.pm | 20 +- lib/PerconaTest.pm | 4 +- lib/QueryRewriter.pm | 2 +- lib/ReplicaLagWaiter.pm | 102 ++-- lib/Safeguards.pm | 94 ---- lib/Sandbox.pm | 58 +-- lib/TableSyncer.pm | 28 +- lib/VariableAdvisorRules.pm | 22 + lib/bash/collect.sh | 13 +- lib/bash/collect_mysql_info.sh | 32 +- lib/bash/report_mysql_info.sh | 96 ++-- t/lib/CompareResults.t | 2 +- t/lib/MasterSlave.t | 128 ++--- t/lib/ReplicaLagWaiter.t | 5 +- t/lib/Safeguards.t | 69 --- t/lib/TableSyncer.t | 2 +- t/lib/bash/report_mysql_info.sh | 8 +- 24 files changed, 576 insertions(+), 1443 deletions(-) delete mode 100644 lib/Percona/Test.pm delete mode 100644 lib/Safeguards.pm delete mode 100644 t/lib/Safeguards.t diff --git a/bin/pt-table-checksum b/bin/pt-table-checksum index fe0e7e22..976349d7 100755 --- a/bin/pt-table-checksum +++ b/bin/pt-table-checksum @@ -5227,20 +5227,20 @@ sub get_slaves { $self->recurse_to_slaves( { dbh => $dbh, dsn => $dsn, - slave_user => $o->got('slave-user') ? $o->get('slave-user') : '', - slave_password => $o->got('slave-password') ? $o->get('slave-password') : '', + slave_user => $o->got('replica-user') ? $o->get('replica-user') : '', + slave_password => $o->got('replica-password') ? $o->get('replica-password') : '', slaves => $args{slaves}, callback => sub { my ( $dsn, $dbh, $level, $parent ) = @_; return unless $level; PTDEBUG && _d('Found slave:', $dp->as_string($dsn)); my $slave_dsn = $dsn; - if ($o->got('slave-user')) { - $slave_dsn->{u} = $o->get('slave-user'); - PTDEBUG && _d("Using slave user ".$o->get('slave-user')." on ".$slave_dsn->{h}.":".$slave_dsn->{P}); + if ($o->got('replica-user')) { + $slave_dsn->{u} = $o->get('replica-user'); + PTDEBUG && _d("Using slave user ".$o->get('replica-user')." on ".$slave_dsn->{h}.":".$slave_dsn->{P}); } - if ($o->got('slave-password')) { - $slave_dsn->{p} = $o->get('slave-password'); + if ($o->got('replica-password')) { + $slave_dsn->{p} = $o->get('replica-password'); PTDEBUG && _d("Slave password set"); } push @$slaves, $make_cxn->(dsn => $slave_dsn, dbh => $dbh, parent => $parent); @@ -13847,7 +13847,7 @@ type: DSN; repeatable: yes DSN to skip when checking slave lag. It can be used multiple times. Example: --skip-check-slave-lag h=127.1,P=12345 --skip-check-slave-lag h=127.1,P=12346 -=item --slave-user +=item --replica-user type: string @@ -13855,12 +13855,12 @@ Sets the user to be used to connect to the slaves. This parameter allows you to have a different user with less privileges on the slaves but that user must exist on all slaves. -=item --slave-password +=item --replica-password type: string Sets the password to be used to connect to the slaves. -It can be used with --slave-user and the password for the user must be the same +It can be used with --replica-user and the password for the user must be the same on all slaves. =item --set-vars diff --git a/bin/pt-variable-advisor b/bin/pt-variable-advisor index 56a6d375..477b4fec 100755 --- a/bin/pt-variable-advisor +++ b/bin/pt-variable-advisor @@ -5609,6 +5609,12 @@ severity: note The init_slave option is enabled on this server. +=item init_replica + +severity: note + +The init_replica option is enabled on this server. + =item innodb_additional_mem_pool_size severity: warn @@ -5862,6 +5868,16 @@ should probably be set to 60 seconds or less. It is also a good idea to use pt-heartbeat to ensure that the connection does not appear to time out when the master is simply idle. +=item replica_net_timeout + +severity: warn + +This variable is set too high. This is too long to wait before +noticing that the connection to the source has failed and retrying. This +should probably be set to 60 seconds or less. It is also a good idea to +use pt-heartbeat to ensure that the connection does not appear to time out +when the source is simply idle. + =item slave_skip_errors severity: crit @@ -5871,6 +5887,15 @@ you need to find and resolve the cause of that; it is likely that your slave's data is different from the master. You can find out with pt-table-checksum. +=item replica_skip_errors + +severity: crit + +You should not set this option. If replication is having errors, +you need to find and resolve the cause of that; it is likely that your +replica's data is different from the source. You can find out with +pt-table-checksum. + =item sort_buffer_size-1 severity: note diff --git a/lib/Cxn.pm b/lib/Cxn.pm index 859a3621..26110cd9 100644 --- a/lib/Cxn.pm +++ b/lib/Cxn.pm @@ -39,8 +39,8 @@ use Scalar::Util qw(blessed); use constant { PTDEBUG => $ENV{PTDEBUG} || 0, # Hostnames make testing less accurate. Tests need to see - # that such-and-such happened on specific slave hosts, but - # the sandbox servers are all on one host so all slaves have + # that such-and-such happened on specific replica hosts, but + # the sandbox servers are all on one host so all replicas have # the same hostname. PERCONA_TOOLKIT_TEST_USE_DSN_NAMES => $ENV{PERCONA_TOOLKIT_TEST_USE_DSN_NAMES} || 0, }; @@ -171,7 +171,7 @@ sub set_dbh { # dbh. dbh_set is required so that if this obj was created with # a dbh, we set that dbh when connect() is called because whoever # created the dbh probably didn't set what we set here. For example, - # MasterSlave makes dbhs when finding slaves, but it doesn't set + # MasterSlave makes dbhs when finding replicas, but it doesn't set # anything. # Due to https://github.com/perl5-dbi/DBD-mysql/issues/306 we assigning # connection_id to $self->{dbh_set} and compare it with current connection_id. diff --git a/lib/MasterSlave.pm b/lib/MasterSlave.pm index 23c992c9..2ac422f2 100644 --- a/lib/MasterSlave.pm +++ b/lib/MasterSlave.pm @@ -19,7 +19,7 @@ # ########################################################################### { # Package: MasterSlave -# MasterSlave handles common tasks related to source-slave setups. +# MasterSlave handles common tasks related to source-replica setups. package MasterSlave; use strict; @@ -60,7 +60,7 @@ sub new { return bless $self, $class; } -sub get_slaves { +sub get_replicas { my ($self, %args) = @_; my @required_args = qw(make_cxn); foreach my $arg ( @required_args ) { @@ -68,11 +68,11 @@ sub get_slaves { } my ($make_cxn) = @args{@required_args}; - my $slaves = []; + my $replicas = []; my $dp = $self->{DSNParser}; my $methods = $self->_resolve_recursion_methods($args{dsn}); - return $slaves unless @$methods; + return $replicas unless @$methods; if ( grep { m/processlist|hosts/i } @$methods ) { my @required_args = qw(dbh dsn); @@ -82,26 +82,26 @@ sub get_slaves { my ($dbh, $dsn) = @args{@required_args}; my $o = $self->{OptionParser}; - $self->recurse_to_slaves( - { dbh => $dbh, - dsn => $dsn, - slave_user => $o->got('slave-user') ? $o->get('slave-user') : '', - slave_password => $o->got('slave-password') ? $o->get('slave-password') : '', - slaves => $args{slaves}, + $self->recurse_to_replicas( + { dbh => $dbh, + dsn => $dsn, + replica_user => $o->got('replica-user') ? $o->get('replica-user') : '', + replica_password => $o->got('replica-password') ? $o->get('replica-password') : '', + replicas => $args{replicas}, callback => sub { my ( $dsn, $dbh, $level, $parent ) = @_; return unless $level; - PTDEBUG && _d('Found slave:', $dp->as_string($dsn)); - my $slave_dsn = $dsn; - if ($o->got('slave-user')) { - $slave_dsn->{u} = $o->get('slave-user'); - PTDEBUG && _d("Using slave user ".$o->get('slave-user')." on ".$slave_dsn->{h}.":".$slave_dsn->{P}); + PTDEBUG && _d('Found replica:', $dp->as_string($dsn)); + my $replica_dsn = $dsn; + if ($o->got('replica-user')) { + $replica_dsn->{u} = $o->get('replica-user'); + PTDEBUG && _d("Using replica user ".$o->get('replica-user')." on ".$replica_dsn->{h}.":".$replica_dsn->{P}); } - if ($o->got('slave-password')) { - $slave_dsn->{p} = $o->get('slave-password'); - PTDEBUG && _d("Slave password set"); + if ($o->got('replica-password')) { + $replica_dsn->{p} = $o->get('replica-password'); + PTDEBUG && _d("Replica password set"); } - push @$slaves, $make_cxn->(dsn => $slave_dsn, dbh => $dbh, parent => $parent); + push @$replicas, $make_cxn->(dsn => $replica_dsn, dbh => $dbh, parent => $parent); return; }, wait_no_die => $args{'wait_no_die'}, @@ -109,20 +109,20 @@ sub get_slaves { ); } elsif ( $methods->[0] =~ m/^dsn=/i ) { (my $dsn_table_dsn = join ",", @$methods) =~ s/^dsn=//i; - $slaves = $self->get_cxn_from_dsn_table( + $replicas = $self->get_cxn_from_dsn_table( %args, dsn_table_dsn => $dsn_table_dsn, wait_no_die => $args{'wait_no_die'}, ); } elsif ( $methods->[0] =~ m/none/i ) { - PTDEBUG && _d('Not getting to slaves'); + PTDEBUG && _d('Not getting to replicas'); } else { die "Unexpected recursion methods: @$methods"; } - return $slaves; + return $replicas; } sub _resolve_recursion_methods { @@ -142,9 +142,9 @@ sub _resolve_recursion_methods { } } -# Sub: recurse_to_slaves -# Descend to slaves by examining SHOW SLAVE HOSTS. -# The callback gets the slave's DSN, dbh, parent, and the recursion level +# Sub: recurse_to_replicas +# Descend to replicas by examining SHOW REPLICAS. +# The callback gets the replica's DSN, dbh, parent, and the recursion level # as args. The recursion is tail recursion. # # Parameters: @@ -154,39 +154,39 @@ sub _resolve_recursion_methods { # Required Arguments: # dsn - The DSN to connect to; if no dbh arg, connect using this. # recurse - How many levels to recurse. 0 = none, undef = infinite. -# callback - Code to execute after finding a new slave. +# callback - Code to execute after finding a new replica. # dsn_parser - object # # Optional Arguments: # dbh - dbh -# skip_callback - Execute with slaves that will be skipped. +# skip_callback - Execute with replicas that will be skipped. # method - Whether to prefer HOSTS over PROCESSLIST # parent - The DSN from which this call descended. -sub recurse_to_slaves { +sub recurse_to_replicas { my ( $self, $args, $level ) = @_; $level ||= 0; my $dp = $self->{DSNParser}; my $recurse = $args->{recurse} || $self->{OptionParser}->get('recurse'); my $dsn = $args->{dsn}; - my $slave_user = $args->{slave_user} || ''; - my $slave_password = $args->{slave_password} || ''; + my $replica_user = $args->{replica_user} || ''; + my $replica_password = $args->{replica_password} || ''; my $methods = $self->_resolve_recursion_methods($dsn); PTDEBUG && _d('Recursion methods:', @$methods); if ( lc($methods->[0]) eq 'none' ) { - PTDEBUG && _d('Not recursing to slaves'); + PTDEBUG && _d('Not recursing to replicas'); return; } - my $slave_dsn = $dsn; - if ($slave_user) { - $slave_dsn->{u} = $slave_user; - PTDEBUG && _d("Using slave user $slave_user on " - . $slave_dsn->{h} . ":" . ( $slave_dsn->{P} ? $slave_dsn->{P} : "")); + my $replica_dsn = $dsn; + if ($replica_user) { + $replica_dsn->{u} = $replica_user; + PTDEBUG && _d("Using replica user $replica_user on " + . $replica_dsn->{h} . ":" . ( $replica_dsn->{P} ? $replica_dsn->{P} : "")); } - if ($slave_password) { - $slave_dsn->{p} = $slave_password; - PTDEBUG && _d("Slave password set"); + if ($replica_password) { + $replica_dsn->{p} = $replica_password; + PTDEBUG && _d("Replica password set"); } my $dbh = $args->{dbh}; @@ -194,12 +194,12 @@ sub recurse_to_slaves { my $get_dbh = sub { eval { $dbh = $dp->get_dbh( - $dp->get_cxn_params($slave_dsn), { AutoCommit => 1 } + $dp->get_cxn_params($replica_dsn), { AutoCommit => 1 } ); - PTDEBUG && _d('Connected to', $dp->as_string($slave_dsn)); + PTDEBUG && _d('Connected to', $dp->as_string($replica_dsn)); }; if ( $EVAL_ERROR ) { - print STDERR "Cannot connect to ", $dp->as_string($slave_dsn), ": ", $EVAL_ERROR, "\n" + print STDERR "Cannot connect to ", $dp->as_string($replica_dsn), ": ", $EVAL_ERROR, "\n" or die "Cannot print: $OS_ERROR"; return; } @@ -207,10 +207,10 @@ sub recurse_to_slaves { DBH: { if ( !defined $dbh ) { - foreach my $known_slave ( @{$args->{slaves}} ) { - if ($known_slave->{dsn}->{h} eq $slave_dsn->{h} and - $known_slave->{dsn}->{P} eq $slave_dsn->{P} ) { - $dbh = $known_slave->{dbh}; + foreach my $known_replica ( @{$args->{replicas}} ) { + if ($known_replica->{dsn}->{h} eq $replica_dsn->{h} and + $known_replica->{dsn}->{P} eq $replica_dsn->{P} ) { + $dbh = $known_replica->{dbh}; last DBH; } } @@ -228,7 +228,7 @@ sub recurse_to_slaves { if ( $EVAL_ERROR ) { if ( $args->{wait_no_die} ) { print STDERR "Error getting server id: ", $EVAL_ERROR, - "\nRetrying query for server ", $slave_dsn->{h}, ":", $slave_dsn->{P}, "\n"; + "\nRetrying query for server ", $replica_dsn->{h}, ":", $replica_dsn->{P}, "\n"; sleep 1; $dbh->disconnect(); $get_dbh->(); @@ -254,63 +254,63 @@ sub recurse_to_slaves { if ( !defined $recurse || $level < $recurse ) { - my @slaves = - grep { !$_->{source_id} || $_->{source_id} == $id } # Only my slaves. - $self->find_slave_hosts($dp, $dbh, $dsn, $methods); + my @replicas = + grep { !$_->{source_id} || $_->{source_id} == $id } # Only my replicas. + $self->find_replica_hosts($dp, $dbh, $dsn, $methods); - foreach my $slave ( @slaves ) { + foreach my $replica ( @replicas ) { PTDEBUG && _d('Recursing from', - $dp->as_string($dsn), 'to', $dp->as_string($slave)); - $self->recurse_to_slaves( - { %$args, dsn => $slave, dbh => undef, parent => $dsn, slave_user => $slave_user, $slave_password => $slave_password }, $level + 1 ); + $dp->as_string($dsn), 'to', $dp->as_string($replica)); + $self->recurse_to_replicas( + { %$args, dsn => $replica, dbh => undef, parent => $dsn, replica_user => $replica_user, $replica_password => $replica_password }, $level + 1 ); } } } -# Finds slave hosts by trying different methods. The default preferred method -# is trying SHOW PROCESSLIST (processlist) and guessing which ones are slaves, -# and if that doesn't reveal anything, then try SHOW SLAVE STATUS (hosts). +# Finds replica hosts by trying different methods. The default preferred method +# is trying SHOW PROCESSLIST (processlist) and guessing which ones are replicas, +# and if that doesn't reveal anything, then try SHOW REPLICA STATUS (hosts). # One exception is if the port is non-standard (3306), indicating that the port -# from SHOW SLAVE HOSTS may be important. Then only the hosts methods is used. +# from SHOW REPLICAS may be important. Then only the hosts methods is used. # # Returns a list of DSN hashes. Optional extra keys in the DSN hash are # source_id and server_id. Also, the 'source' key is either 'processlist' or # 'hosts'. # # If a method is given, it becomes the preferred (first tried) method. -# Searching stops as soon as a method finds slaves. -sub find_slave_hosts { +# Searching stops as soon as a method finds replicas. +sub find_replica_hosts { my ( $self, $dsn_parser, $dbh, $dsn, $methods ) = @_; - PTDEBUG && _d('Looking for slaves on', $dsn_parser->as_string($dsn), + PTDEBUG && _d('Looking for replicas on', $dsn_parser->as_string($dsn), 'using methods', @$methods); - my @slaves; + my @replicas; METHOD: foreach my $method ( @$methods ) { - my $find_slaves = "_find_slaves_by_$method"; - PTDEBUG && _d('Finding slaves with', $find_slaves); - @slaves = $self->$find_slaves($dsn_parser, $dbh, $dsn); - last METHOD if @slaves; + my $find_replicas = "_find_replicas_by_$method"; + PTDEBUG && _d('Finding replicas with', $find_replicas); + @replicas = $self->$find_replicas($dsn_parser, $dbh, $dsn); + last METHOD if @replicas; } - PTDEBUG && _d('Found', scalar(@slaves), 'slaves'); - return @slaves; + PTDEBUG && _d('Found', scalar(@replicas), 'replicas'); + return @replicas; } -sub _find_slaves_by_processlist { +sub _find_replicas_by_processlist { my ( $self, $dsn_parser, $dbh, $dsn ) = @_; - my @connected_slaves = $self->get_connected_slaves($dbh); - my @slaves = $self->_process_slaves_list($dsn_parser, $dsn, \@connected_slaves); - return @slaves; + my @connected_replicas = $self->get_connected_replicas($dbh); + my @replicas = $self->_process_replicas_list($dsn_parser, $dsn, \@connected_replicas); + return @replicas; } -sub _process_slaves_list { - my ($self, $dsn_parser, $dsn, $connected_slaves) = @_; - my @slaves = map { - my $slave = $dsn_parser->parse("h=$_", $dsn); - $slave->{source} = 'processlist'; - $slave; +sub _process_replicas_list { + my ($self, $dsn_parser, $dsn, $connected_replicas) = @_; + my @replicas = map { + my $replica = $dsn_parser->parse("h=$_", $dsn); + $replica->{source} = 'processlist'; + $replica; } grep { $_ } map { @@ -322,32 +322,34 @@ sub _process_slaves_list { $host = '['.$host.']'; } $host; - } @$connected_slaves; + } @$connected_replicas; - return @slaves; + return @replicas; } -# SHOW SLAVE HOSTS is significantly less reliable. +# SHOW REPLICAS is significantly less reliable. # Machines tend to share the host list around with every machine in the # replication hierarchy, but they don't update each other when machines # disconnect or change to use a different source or something. So there is -# lots of cruft in SHOW SLAVE HOSTS. -sub _find_slaves_by_hosts { +# lots of cruft in SHOW REPLICAS. +sub _find_replicas_by_hosts { my ( $self, $dsn_parser, $dbh, $dsn ) = @_; - my @slaves; - my $server_version = VersionParser->new($dbh); + my @replicas; + + my $vp = VersionParser->new($dbh); my $sql = 'SHOW REPLICAS'; - if ( $server_version < '8.1' || $server_version->flavor() =~ m/maria/ ) { + if ( $vp < '8.1' || $vp->flavor() =~ m/maria/ ) { $sql = 'SHOW SLAVE HOSTS'; } + PTDEBUG && _d($dbh, $sql); - @slaves = @{$dbh->selectall_arrayref($sql, { Slice => {} })}; + @replicas = @{$dbh->selectall_arrayref($sql, { Slice => {} })}; - # Convert SHOW SLAVE HOSTS into DSN hashes. - if ( @slaves ) { - PTDEBUG && _d('Found some SHOW SLAVE HOSTS info'); - @slaves = map { + # Convert SHOW REPLICAS into DSN hashes. + if ( @replicas ) { + PTDEBUG && _d('Found some SHOW REPLICAS info'); + @replicas = map { my %hash; @hash{ map { lc $_ } keys %$_ } = values %$_; my $spec = "h=$hash{host},P=$hash{port}" @@ -358,15 +360,15 @@ sub _find_slaves_by_hosts { $dsn->{source_id} = $hash{source_id}; $dsn->{source} = 'hosts'; $dsn; - } @slaves; + } @replicas; } - return @slaves; + return @replicas; } -# Returns PROCESSLIST entries of connected slaves, normalized to lowercase +# Returns PROCESSLIST entries of connected replicas, normalized to lowercase # column names. -sub get_connected_slaves { +sub get_connected_replicas { my ( $self, $dbh ) = @_; # Check for the PROCESS privilege. @@ -407,7 +409,7 @@ sub get_connected_slaves { $sql = 'SHOW FULL PROCESSLIST'; PTDEBUG && _d($dbh, $sql); - # It's probably a slave if it's doing a binlog dump. + # It's probably a replica if it's doing a binlog dump. grep { $_->{command} =~ m/Binlog Dump/i } map { # Lowercase the column names my %hash; @@ -417,13 +419,13 @@ sub get_connected_slaves { @{$dbh->selectall_arrayref($sql, { Slice => {} })}; } -# Verifies that $source is really the source of $slave. This is not an exact +# Verifies that $source is really the source of $replica. This is not an exact # science, but there is a decent chance of catching some obvious cases when it # is not the source. If not the source, it dies; otherwise returns true. sub is_source_of { - my ( $self, $source, $slave ) = @_; + my ( $self, $source, $replica ) = @_; - my $replica_version = VersionParser->new($slave); + my $replica_version = VersionParser->new($replica); my $source_name = 'source'; my $source_port = 'source_port'; if ( $replica_version < '8.1' || $replica_version->flavor() =~ m/maria/ ) { @@ -433,47 +435,47 @@ sub is_source_of { my $source_status = $self->get_source_status($source) or die "The server specified as a source is not a source"; - my $slave_status = $self->get_slave_status($slave) - or die "The server specified as a slave is not a slave"; - my @connected = $self->get_connected_slaves($source) - or die "The server specified as a source has no connected slaves"; + my $replica_status = $self->get_replica_status($replica) + or die "The server specified as a replica is not a replica"; + my @connected = $self->get_connected_replicas($source) + or die "The server specified as a source has no connected replicas"; my (undef, $port) = $source->selectrow_array("SHOW VARIABLES LIKE 'port'"); - if ( $port != $slave_status->{$source_port} ) { - die "The slave is connected to $slave_status->{$source_port} " + if ( $port != $replica_status->{$source_port} ) { + die "The replica is connected to $replica_status->{$source_port} " . "but the source's port is $port"; } - if ( !grep { $slave_status->{source_user} eq $_->{user} } @connected ) { - die "I don't see any slave I/O thread connected with user " - . $slave_status->{source_user}; + if ( !grep { $replica_status->{source_user} eq $_->{user} } @connected ) { + die "I don't see any replica I/O thread connected with user " + . $replica_status->{source_user}; } - if ( ($slave_status->{slave_io_state} || '') + if ( ($replica_status->{replica_io_state} || '') eq 'Waiting for ${source_name} to send event' ) { - # The slave thinks its I/O thread is caught up to the source. Let's - # compare and make sure the source and slave are reasonably close to each + # The replica thinks its I/O thread is caught up to the source. Let's + # compare and make sure the source and replica are reasonably close to each # other. Note that this is one of the few places where I check the I/O # thread positions instead of the SQL thread positions! # Source_Log_File/Read_Source_Log_Pos is the I/O thread's position on the # source. my ( $source_log_name, $source_log_num ) = $source_status->{file} =~ m/^(.*?)\.0*([1-9][0-9]*)$/; - my ( $slave_log_name, $slave_log_num ) - = $slave_status->{source_log_file} =~ m/^(.*?)\.0*([1-9][0-9]*)$/; - if ( $source_log_name ne $slave_log_name - || abs($source_log_num - $slave_log_num) > 1 ) + my ( $replica_log_name, $replica_log_num ) + = $replica_status->{source_log_file} =~ m/^(.*?)\.0*([1-9][0-9]*)$/; + if ( $source_log_name ne $replica_log_name + || abs($source_log_num - $replica_log_num) > 1 ) { - die "The slave thinks it is reading from " - . "$slave_status->{source_log_file}, but the " + die "The replica thinks it is reading from " + . "$replica_status->{source_log_file}, but the " . "source is writing to $source_status->{file}"; } } return 1; } -# Figures out how to connect to the source, by examining SHOW SLAVE STATUS. But +# Figures out how to connect to the source, by examining SHOW REPLICA STATUS. But # does NOT use the value from Source_User for the username, because typically we # want to perform operations as the username that was specified (usually to the # program's --user option, or in a DSN), rather than as the replication user, @@ -489,29 +491,29 @@ sub get_source_dsn { $source_port = 'master_port'; } - my $source = $self->get_slave_status($dbh) or return undef; + my $source = $self->get_replica_status($dbh) or return undef; my $spec = "h=$source->{${source_host}},P=$source->{${source_port}}"; return $dsn_parser->parse($spec, $dsn); } -# Gets SHOW SLAVE STATUS, with column names all lowercased, as a hashref. -sub get_slave_status { +# Gets SHOW REPLICA STATUS, with column names all lowercased, as a hashref. +sub get_replica_status { my ( $self, $dbh ) = @_; my $server_version = VersionParser->new($dbh); my $replica_name = 'replica'; if ( $server_version < '8.1' || $server_version->flavor() =~ m/maria/ ) { - $replica_name = 'slave'; + $replica_name = 'replica'; } - if ( !$self->{not_a_slave}->{$dbh} ) { - my $sth = $self->{sths}->{$dbh}->{SLAVE_STATUS} + if ( !$self->{not_a_replica}->{$dbh} ) { + my $sth = $self->{sths}->{$dbh}->{REPLICA_STATUS} ||= $dbh->prepare("SHOW ${replica_name} STATUS"); PTDEBUG && _d($dbh, "SHOW ${replica_name} STATUS"); $sth->execute(); - my ($sss_rows) = $sth->fetchall_arrayref({}); # Show Slave Status rows + my ($sss_rows) = $sth->fetchall_arrayref({}); # Show Replica Status rows - # If SHOW SLAVE STATUS returns more than one row it means that this slave is connected to more + # If SHOW REPLICA STATUS returns more than one row it means that this replica is connected to more # than one source using replication channels. # If we have a channel name as a parameter, we need to select the correct row and return it. # If we don't have a channel name as a parameter, there is no way to know what the correct source is so, @@ -520,20 +522,20 @@ sub get_slave_status { if ( $sss_rows && @$sss_rows ) { if (scalar @$sss_rows > 1) { if (!$self->{channel}) { - die 'This server returned more than one row for SHOW SLAVE STATUS but "channel" was not specified on the command line'; + die 'This server returned more than one row for SHOW REPLICA STATUS but "channel" was not specified on the command line'; } - my $slave_use_channels; + my $replica_use_channels; for my $row (@$sss_rows) { $row = { map { lc($_) => $row->{$_} } keys %$row }; # lowercase the keys if ($row->{channel_name}) { - $slave_use_channels = 1; + $replica_use_channels = 1; } if ($row->{channel_name} eq $self->{channel}) { $ss = $row; last; } } - if (!$ss && $slave_use_channels) { + if (!$ss && $replica_use_channels) { die 'This server is using replication channels but "channel" was not specified on the command line'; } } else { @@ -553,8 +555,8 @@ sub get_slave_status { } } - PTDEBUG && _d('This server returns nothing for SHOW SLAVE STATUS'); - $self->{not_a_slave}->{$dbh}++; + PTDEBUG && _d('This server returns nothing for SHOW REPLICA STATUS'); + $self->{not_a_replica}->{$dbh}++; } } @@ -597,14 +599,14 @@ sub get_source_status { } # Sub: wait_for_source -# Execute SOURCE_POS_WAIT() to make slave wait for its source. +# Execute SOURCE_POS_WAIT() to make replica wait for its source. # # Parameters: # %args - Arguments # # Required Arguments: # * source_status - Hashref returned by -# * slave_dbh - dbh for slave host +# * replica_dbh - dbh for replica host # # Optional Arguments: # * timeout - Wait time in seconds (default 60) @@ -619,41 +621,41 @@ sub get_source_status { # (end code) sub wait_for_source { my ( $self, %args ) = @_; - my @required_args = qw(source_status slave_dbh); + my @required_args = qw(source_status replica_dbh); foreach my $arg ( @required_args ) { die "I need a $arg argument" unless $args{$arg}; } - my ($source_status, $slave_dbh) = @args{@required_args}; + my ($source_status, $replica_dbh) = @args{@required_args}; my $timeout = $args{timeout} || 60; my $result; my $waited; if ( $source_status ) { - my $slave_status; + my $replica_status; eval { - $slave_status = $self->get_slave_status($slave_dbh); + $replica_status = $self->get_replica_status($replica_dbh); }; if ($EVAL_ERROR) { return { result => undef, waited => 0, - error =>'Wait for source: this is a multi-source slave but "channel" was not specified on the command line', + error =>'Wait for source: this is a multi-source replica but "channel" was not specified on the command line', }; } - my $vp = VersionParser->new($slave_dbh); + my $vp = VersionParser->new($replica_dbh); my $source_name = 'source'; if ( $vp < '8.1' || $vp->flavor() =~ m/maria/ ) { $source_name = 'master'; } my $channel_sql = $vp > '5.6' && $self->{channel} ? ", '$self->{channel}'" : ''; my $sql = "SELECT ${source_name}_POS_WAIT('$source_status->{file}', $source_status->{position}, $timeout $channel_sql)"; - PTDEBUG && _d($slave_dbh, $sql); + PTDEBUG && _d($replica_dbh, $sql); my $start = time; - ($result) = $slave_dbh->selectrow_array($sql); + ($result) = $replica_dbh->selectrow_array($sql); # If SOURCE_POS_WAIT() returned NULL and we waited at least 1s # and the time we waited is less than the timeout then this is - # a strong indication that the slave was stopped while we were + # a strong indication that the replica was stopped while we were # waiting. $waited = time - $start; @@ -670,23 +672,24 @@ sub wait_for_source { }; } -# Executes STOP SLAVE. -sub stop_slave { +# Executes STOP REPLICA. +sub stop_replica { my ( $self, $dbh ) = @_; my $vp = VersionParser->new($dbh); my $replica_name = 'replica'; if ( $vp < '8.1' || $vp->flavor() =~ m/maria/ ) { - $replica_name = 'slave'; + $replica_name = 'replica'; } - my $sth = $self->{sths}->{$dbh}->{STOP_SLAVE} + my $sth = $self->{sths}->{$dbh}->{STOP_REPLICA} ||= $dbh->prepare("STOP ${replica_name}"); PTDEBUG && _d($dbh, $sth->{Statement}); $sth->execute(); } -# Executes START SLAVE, optionally with UNTIL. -sub start_slave { +# Executes START REPLICA, optionally with UNTIL. +sub start_replica { my ( $self, $dbh, $pos ) = @_; + my $vp = VersionParser->new($dbh); my $source_name = 'source'; my $replica_name = 'replica'; @@ -694,6 +697,7 @@ sub start_slave { $source_name = 'master'; $replica_name = 'slave'; } + if ( $pos ) { # Just like with CHANGE REPLICATION SOURCE TO, you can't quote the position. my $sql = "START ${replica_name} UNTIL ${source_name}_LOG_FILE='$pos->{file}', " @@ -702,40 +706,40 @@ sub start_slave { $dbh->do($sql); } else { - my $sth = $self->{sths}->{$dbh}->{START_SLAVE} + my $sth = $self->{sths}->{$dbh}->{START_REPLICA} ||= $dbh->prepare("START ${replica_name}"); PTDEBUG && _d($dbh, $sth->{Statement}); $sth->execute(); } } -# Waits for the slave to catch up to its source, using START SLAVE UNTIL. When -# complete, the slave is caught up to the source, and the slave process is +# Waits for the replica to catch up to its source, using START REPLICA UNTIL. When +# complete, the replica is caught up to the source, and the replica process is # stopped on both servers. sub catchup_to_source { - my ( $self, $slave, $source, $timeout ) = @_; - $self->stop_slave($source); - $self->stop_slave($slave); - my $slave_status = $self->get_slave_status($slave); - my $slave_pos = $self->repl_posn($slave_status); + my ( $self, $replica, $source, $timeout ) = @_; + $self->stop_replica($source); + $self->stop_replica($replica); + my $replica_status = $self->get_replica_status($replica); + my $replica_pos = $self->repl_posn($replica_status); my $source_status = $self->get_source_status($source); my $source_pos = $self->repl_posn($source_status); PTDEBUG && _d('Source position:', $self->pos_to_string($source_pos), - 'Slave position:', $self->pos_to_string($slave_pos)); + 'Replica position:', $self->pos_to_string($replica_pos)); my $result; - if ( $self->pos_cmp($slave_pos, $source_pos) < 0 ) { - PTDEBUG && _d('Waiting for slave to catch up to source'); - $self->start_slave($slave, $source_pos); + if ( $self->pos_cmp($replica_pos, $source_pos) < 0 ) { + PTDEBUG && _d('Waiting for replica to catch up to source'); + $self->start_replica($replica, $source_pos); - # The slave may catch up instantly and stop, in which case + # The replica may catch up instantly and stop, in which case # SOURCE_POS_WAIT will return NULL and $result->{result} will be undef. # We must catch this; if it returns NULL, then we check that # its position is as desired. # TODO: what if source_pos_wait times out and $result == -1? retry? $result = $self->wait_for_source( source_status => $source_status, - slave_dbh => $slave, + replica_dbh => $replica, timeout => $timeout, source_status => $source_status ); @@ -743,25 +747,32 @@ sub catchup_to_source { die $result->{error}; } if ( !defined $result->{result} ) { - $slave_status = $self->get_slave_status($slave); - if ( !$self->slave_is_running($slave_status) ) { + $replica_status = $self->get_replica_status($replica); + + my $vp = VersionParser->new($replica); + my $replica_name = 'replica'; + if ( $vp < '8.1' || $vp->flavor() =~ m/maria/ ) { + $replica_name = 'slave'; + } + + if ( !$self->replica_is_running($replica_status, $replica_name) ) { PTDEBUG && _d('Source position:', $self->pos_to_string($source_pos), - 'Slave position:', $self->pos_to_string($slave_pos)); - $slave_pos = $self->repl_posn($slave_status); - if ( $self->pos_cmp($slave_pos, $source_pos) != 0 ) { - die "SOURCE_POS_WAIT() returned NULL but slave has not " + 'Replica position:', $self->pos_to_string($replica_pos)); + $replica_pos = $self->repl_posn($replica_status); + if ( $self->pos_cmp($replica_pos, $source_pos) != 0 ) { + die "SOURCE_POS_WAIT() returned NULL but replica has not " . "caught up to source"; } - PTDEBUG && _d('Slave is caught up to source and stopped'); + PTDEBUG && _d('Replica is caught up to source and stopped'); } else { - die "Slave has not caught up to source and it is still running"; + die "Replica has not caught up to source and it is still running"; } } } else { - PTDEBUG && _d("Slave is already caught up to source"); + PTDEBUG && _d("Replica is already caught up to source"); } return $result; @@ -771,28 +782,40 @@ sub catchup_to_source { # servers are stopped and at the same position. sub catchup_to_same_pos { my ( $self, $s1_dbh, $s2_dbh ) = @_; - $self->stop_slave($s1_dbh); - $self->stop_slave($s2_dbh); - my $s1_status = $self->get_slave_status($s1_dbh); - my $s2_status = $self->get_slave_status($s2_dbh); + $self->stop_replica($s1_dbh); + $self->stop_replica($s2_dbh); + my $s1_status = $self->get_replica_status($s1_dbh); + my $s2_status = $self->get_replica_status($s2_dbh); my $s1_pos = $self->repl_posn($s1_status); my $s2_pos = $self->repl_posn($s2_status); if ( $self->pos_cmp($s1_pos, $s2_pos) < 0 ) { - $self->start_slave($s1_dbh, $s2_pos); + $self->start_replica($s1_dbh, $s2_pos); } elsif ( $self->pos_cmp($s2_pos, $s1_pos) < 0 ) { - $self->start_slave($s2_dbh, $s1_pos); + $self->start_replica($s2_dbh, $s1_pos); } # Re-fetch the replication statuses and positions. - $s1_status = $self->get_slave_status($s1_dbh); - $s2_status = $self->get_slave_status($s2_dbh); + $s1_status = $self->get_replica_status($s1_dbh); + $s2_status = $self->get_replica_status($s2_dbh); $s1_pos = $self->repl_posn($s1_status); $s2_pos = $self->repl_posn($s2_status); + my $vp1 = VersionParser->new($s1_dbh); + my $replica1_name = 'replica'; + if ( $vp1 < '8.1' || $vp1->flavor() =~ m/maria/ ) { + $replica1_name = 'slave'; + } + + my $vp2 = VersionParser->new($s2_dbh); + my $replica2_name = 'replica'; + if ( $vp2 < '8.1' || $vp2->flavor() =~ m/maria/ ) { + $replica2_name = 'slave'; + } + # Verify that they are both stopped and are at the same position. - if ( $self->slave_is_running($s1_status) - || $self->slave_is_running($s2_status) + if ( $self->replica_is_running($s1_status, $replica1_name) + || $self->replica_is_running($s2_status, $replica2_name) || $self->pos_cmp($s1_pos, $s2_pos) != 0) { die "The servers aren't both stopped at the same position"; @@ -800,23 +823,30 @@ sub catchup_to_same_pos { } -# Returns true if the slave is running. -sub slave_is_running { - my ( $self, $slave_status ) = @_; - return ($slave_status->{slave_sql_running} || 'No') eq 'Yes'; +# Returns true if the replica is running. +sub replica_is_running { + my ( $self, $replica_status, $replica_name ) = @_; + return ($replica_status->{"${replica_name}_sql_running"} || 'No') eq 'Yes'; } -# Returns true if the server's log_slave_updates option is enabled. -sub has_slave_updates { +# Returns true if the server's log_replica_updates option is enabled. +sub has_replica_updates { my ( $self, $dbh ) = @_; - my $sql = q{SHOW VARIABLES LIKE 'log_slave_updates'}; + + my $vp = VersionParser->new($dbh); + my $replica_name = 'replica'; + if ( $vp < '8.1' || $vp->flavor() =~ m/maria/ ) { + $replica_name = 'slave'; + } + + my $sql = qq{SHOW VARIABLES LIKE 'log_${replica_name}_updates'}; PTDEBUG && _d($dbh, $sql); my ($name, $value) = $dbh->selectrow_array($sql); return $value && $value =~ m/^(1|ON)$/; } # Extracts the replication position out of either SHOW REPLICATION SOURCE STATUS or SHOW -# SLAVE STATUS, and returns it as a hashref { file, position } +# REPLICA STATUS, and returns it as a hashref { file, position } sub repl_posn { my ( $self, $status ) = @_; if ( exists $status->{file} && exists $status->{position} ) { @@ -841,8 +871,8 @@ sub repl_posn { } } -# Gets the slave's lag. TODO: permit using a heartbeat table. -sub get_slave_lag { +# Gets the replica's lag. TODO: permit using a heartbeat table. +sub get_replica_lag { my ( $self, $dbh ) = @_; my $vp = VersionParser->new($dbh); @@ -851,8 +881,8 @@ sub get_slave_lag { $source_name = 'master'; } - my $stat = $self->get_slave_status($dbh); - return unless $stat; # server is not a slave + my $stat = $self->get_replica_status($dbh); + return unless $stat; # server is not a replica return $stat->{"seconds_behind_${source_name}"}; } @@ -868,7 +898,7 @@ sub pos_cmp { # hostname is really just the combination of hostname and port, since # replication always uses TCP connections (it does not work via sockets). If # the port is the default 3306, it is omitted. As a convenience, this sub -# accepts either SHOW SLAVE STATUS or a DSN. +# accepts either SHOW REPLICA STATUS or a DSN. # # Parameters: # $dsn - DSN hashref @@ -898,7 +928,7 @@ sub short_host { # # Arguments: # type - Which kind of repl thread to match: -# all, binlog_dump (source), slave_io, or slave_sql +# all, binlog_dump (source), replica_io, or replica_sql # (default: all) # check_known_ids - Check known replication thread IDs (default: yes) # @@ -910,7 +940,7 @@ sub is_replication_thread { my $type = lc($args{type} || 'all'); die "Invalid type: $type" - unless $type =~ m/^binlog_dump|slave_io|slave_sql|all$/i; + unless $type =~ m/^binlog_dump|slave_io|slave_sql|replica_io|replica_sql|all$/i; my $match = 0; if ( $type =~ m/binlog_dump|all/i ) { @@ -918,11 +948,11 @@ sub is_replication_thread { if ($query->{Command} || $query->{command} || '') eq "Binlog Dump"; } if ( !$match ) { - # On a slave, there are two threads. Both have user="system user". + # On a replica, there are two threads. Both have user="system user". if ( ($query->{User} || $query->{user} || '') eq "system user" ) { - PTDEBUG && _d("Slave replication thread"); + PTDEBUG && _d("Replica replication thread"); if ( $type ne 'all' ) { - # Match a particular slave thread. + # Match a particular replica thread. my $state = $query->{State} || $query->{state} || ''; if ( $state =~ m/^init|end$/ ) { @@ -932,27 +962,28 @@ sub is_replication_thread { } else { # These patterns are abbreviated because if the first few words - # match chances are very high it's the full slave thd state. - my ($slave_sql) = $state =~ m/ + # match chances are very high it's the full replica thd state. + my ($replica_sql) = $state =~ m/ ^(Waiting\sfor\sthe\snext\sevent |Reading\sevent\sfrom\sthe\srelay\slog |Has\sread\sall\srelay\slog;\swaiting |Making\stemp\sfile - |Waiting\sfor\sslave\smutex\son\sexit)/xi; + |Waiting\sfor\sslave\smutex\son\sexit + |Waiting\sfor\sreplica\smutex\son\sexit)/xi; - # Type is either "slave_sql" or "slave_io". The second line + # Type is either "replica_sql" or "replica_io". The second line # implies that if this isn't the sql thread then it must be # the io thread, so match is true if we were supposed to match # the io thread. - $match = $type eq 'slave_sql' && $slave_sql ? 1 - : $type eq 'slave_io' && !$slave_sql ? 1 + $match = $type eq 'replica_sql' && $replica_sql ? 1 + : $type eq 'replica_io' && !$replica_sql ? 1 : 0; } } else { # Type is "all" and it's not a source (binlog_dump) thread, # else we wouldn't have gotten here. It's either of the 2 - # slave threads and we don't care which. + # replica threads and we don't care which. $match = 1; } } @@ -960,9 +991,9 @@ sub is_replication_thread { PTDEBUG && _d('Not system user'); } - # MySQL loves to trick us. Sometimes a slave replication thread will + # MySQL loves to trick us. Sometimes a replica replication thread will # temporarily morph into what looks like a regular user thread when - # really it's still the same slave repl thread. So here we save known + # really it's still the same replica repl thread. So here we save known # repl thread IDs and check if a non-matching event is actually a # known repl thread ID and if yes then we make it match. if ( !defined $args{check_known_ids} || $args{check_known_ids} ) { @@ -993,7 +1024,7 @@ sub is_replication_thread { # %args - Arguments # # Required Arguments: -# dbh - dbh, source or slave +# dbh - dbh, source or replica # # Returns: # Hashref of any replication filters. If none are set, an empty hashref @@ -1006,6 +1037,12 @@ sub get_replication_filters { } my ($dbh) = @args{@required_args}; + my $vp = VersionParser->new($dbh); + my $replica_name = 'replica'; + if ( $vp < '8.1' || $vp->flavor() =~ m/maria/ ) { + $replica_name = 'slave'; + } + my %filters = (); my $status = $self->get_source_status($dbh); @@ -1018,7 +1055,7 @@ sub get_replication_filters { ); } - $status = $self->get_slave_status($dbh); + $status = $self->get_replica_status($dbh); if ( $status ) { map { $filters{$_} = $status->{$_} } grep { defined $status->{$_} && $status->{$_} ne '' } @@ -1031,11 +1068,11 @@ sub get_replication_filters { replicate_wild_ignore_table ); - my $sql = "SHOW VARIABLES LIKE 'slave_skip_errors'"; + my $sql = "SHOW VARIABLES LIKE '${replica_name}_skip_errors'"; PTDEBUG && _d($dbh, $sql); my $row = $dbh->selectrow_arrayref($sql); # "OFF" in 5.0, "" in 5.1 - $filters{slave_skip_errors} = $row->[1] if $row->[1] && $row->[1] ne 'OFF'; + $filters{replica_skip_errors} = $row->[1] if $row->[1] && $row->[1] ne 'OFF'; } return \%filters; diff --git a/lib/MySQLConfig.pm b/lib/MySQLConfig.pm index 9c6cf272..c21dd072 100644 --- a/lib/MySQLConfig.pm +++ b/lib/MySQLConfig.pm @@ -282,7 +282,7 @@ sub parse_mysqld { # and boolean options {FALSE|TRUE} Value (after reading options) # --------------------------------- ----------------------------- # help TRUE - # abort-slave-event-count 0 + # auto_increment_increment 1 # So we search for that line of hyphens. # # It also ends with something like diff --git a/lib/MySQLProtocolParser.pm b/lib/MySQLProtocolParser.pm index f81dc55f..050fadff 100644 --- a/lib/MySQLProtocolParser.pm +++ b/lib/MySQLProtocolParser.pm @@ -75,7 +75,7 @@ use constant { COM_BINLOG_DUMP => '12', COM_TABLE_DUMP => '13', COM_CONNECT_OUT => '14', - COM_REGISTER_SLAVE => '15', + COM_REGISTER_REPLICA => '15', COM_STMT_PREPARE => '16', COM_STMT_EXECUTE => '17', COM_STMT_SEND_LONG_DATA => '18', @@ -109,7 +109,7 @@ my %com_for = ( '12' => 'COM_BINLOG_DUMP', '13' => 'COM_TABLE_DUMP', '14' => 'COM_CONNECT_OUT', - '15' => 'COM_REGISTER_SLAVE', + '15' => 'COM_REGISTER_REPLICA', '16' => 'COM_STMT_PREPARE', '17' => 'COM_STMT_EXECUTE', '18' => 'COM_STMT_SEND_LONG_DATA', diff --git a/lib/Percona/Test.pm b/lib/Percona/Test.pm deleted file mode 100644 index e1221b49..00000000 --- a/lib/Percona/Test.pm +++ /dev/null @@ -1,814 +0,0 @@ -# This program is copyright 2009-2013 Percona Inc. -# Feedback and improvements are welcome. -# -# THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED -# WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF -# MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. -# -# This program is free software; you can redistribute it and/or modify it under -# the terms of the GNU General Public License as published by the Free Software -# Foundation, version 2; OR the Perl Artistic License. On UNIX and similar -# systems, you can issue `man perlgpl' or `man perlartistic' to read these -# licenses. -# -# You should have received a copy of the GNU General Public License along with -# this program; if not, write to the Free Software Foundation, Inc., 59 Temple -# Place, Suite 330, Boston, MA 02111-1307 USA. -# ########################################################################### -# Percona::Test package -# ########################################################################### -{ -# Package: Percona::Test -# PerconaTest is a collection of helper-subs for Percona Toolkit tests. -# Any file arguments (like no_diff() $expected_output) are relative to -# PERCONA_TOOLKIT_BRANCH. So passing "commont/t/samples/foo" means -# "PERCONA_TOOLKIT_BRANCH/common/t/samples/foo". Do not BAIL_OUT() because -# this terminates the *entire* test process; die instead. All -# subs are exported by default, so is the variable $trunk, so there's -# no need to import() in the test scripts. -package Percona::Test; - -use strict; -use warnings FATAL => 'all'; -use English qw(-no_match_vars); -use constant PTDEVDEBUG => $ENV{PTDEVDEBUG} || 0; - -use Data::Dumper; -$Data::Dumper::Indent = 1; -$Data::Dumper::Sortkeys = 1; -$Data::Dumper::Quotekeys = 0; - -use Test::More; -use Time::HiRes qw(sleep time); -use File::Temp qw(tempfile); -use POSIX qw(signal_h); - -require Exporter; -our @ISA = qw(Exporter); -our %EXPORT_TAGS = (); -our @EXPORT_OK = qw(); -our @EXPORT = qw( - output - full_output - load_data - load_file - slurp_file - parse_file - wait_until - wait_for - wait_until_slave_running - wait_until_no_lag - test_log_parser - test_protocol_parser - test_packet_parser - no_diff - throws_ok - remove_traces - test_bash_tool - verify_test_data_integrity - $trunk - $dsn_opts - $sandbox_version - $can_load_data -); - -our $trunk = $ENV{PERCONA_TOOLKIT_BRANCH}; - -our $sandbox_version = ''; -eval { - chomp(my $v = `$trunk/sandbox/test-env version 2>/dev/null`); - $sandbox_version = $v if $v; -}; - -our $can_load_data = can_load_data(); - -our $dsn_opts = [ - { - key => 'A', - desc => 'Default character set', - dsn => 'charset', - copy => 1, - }, - { - key => 'D', - desc => 'Database to use', - dsn => 'database', - copy => 1, - }, - { - key => 'F', - desc => 'Only read default options from the given file', - dsn => 'mysql_read_default_file', - copy => 1, - }, - { - key => 'h', - desc => 'Connect to host', - dsn => 'host', - copy => 1, - }, - { - key => 'p', - desc => 'Password to use when connecting', - dsn => 'password', - copy => 1, - }, - { - key => 'P', - desc => 'Port number to use for connection', - dsn => 'port', - copy => 1, - }, - { - key => 'S', - desc => 'Socket file to use for connection', - dsn => 'mysql_socket', - copy => 1, - }, - { - key => 't', - desc => 'Table', - dsn => undef, - copy => 1, - }, - { - key => 'u', - desc => 'User for login if not current user', - dsn => 'user', - copy => 1, - }, -]; - -# Runs code, captures and returns its output. -# Optional arguments: -# * file scalar: capture output to this file (default none) -# * stderr scalar: capture STDERR (default no) -# * die scalar: die if code dies (default no) -# * trf coderef: pass output to this coderef (default none) -sub output { - my ( $code, %args ) = @_; - die "I need a code argument" unless $code; - my ($file, $stderr, $die, $trf) = @args{qw(file stderr die trf)}; - - if ( $args{debug} ) { - my $retval = eval { $code->() }; - warn $EVAL_ERROR if $EVAL_ERROR; - return $retval; - } - - my $output = ''; - { - if ( $file ) { - open *output_fh, '>', $file - or die "Cannot open file $file: $OS_ERROR"; - } - else { - open *output_fh, '>', \$output - or die "Cannot capture output to variable: $OS_ERROR"; - } - local *STDOUT = *output_fh; - - # If capturing STDERR we must dynamically scope (local) STDERR - # in the outer scope of the sub. If we did, - # if ( $args{stderr} ) { local *STDERR; ... } - # then STDERR would revert to its original value outside the if - # block. - local *STDERR if $args{stderr}; # do in outer scope of this sub - *STDERR = *STDOUT if $args{stderr}; - - eval { $code->() }; - if ( $EVAL_ERROR ) { - die $EVAL_ERROR if $die; - warn $EVAL_ERROR; - } - - close *output_fh; - } - - select STDOUT; - - # Possible transform output before returning it. This doesn't work - # if output was captured to a file. - $output = $trf->($output) if $trf; - - return $output; -} - -# Load data from file and removes spaces. Used to load tcpdump dumps. -sub load_data { - my ( $file ) = @_; - $file = "$trunk/$file"; - open my $fh, '<', $file or die "Cannot open $file: $OS_ERROR"; - my $contents = do { local $/ = undef; <$fh> }; - close $fh; - (my $data = join('', $contents =~ m/(.*)/g)) =~ s/\s+//g; - return $data; -} - -# Slurp file and return its entire contents. -sub load_file { - my ( $file, %args ) = @_; - $file = "$trunk/$file"; - my $contents = slurp_file($file); - chomp $contents if $args{chomp_contents}; - return $contents; -} - -sub slurp_file { - my ($file) = @_; - open my $fh, "<", $file or die "Cannot open $file: $OS_ERROR"; - my $contents = do { local $/ = undef; <$fh> }; - close $fh; - return $contents; -} - -sub parse_file { - my ( $file, $p, $ea ) = @_; - $file = "$trunk/$file"; - my @e; - eval { - open my $fh, "<", $file or die "Cannot open $file: $OS_ERROR"; - my %args = ( - next_event => sub { return <$fh>; }, - tell => sub { return tell $fh; }, - fh => $fh, - ); - while ( my $e = $p->parse_event(%args) ) { - push @e, $e; - $ea->aggregate($e) if $ea; - } - close $fh; - }; - die $EVAL_ERROR if $EVAL_ERROR; - return \@e; -} - -# Wait until code returns true. -sub wait_until { - my ( $code, $t, $max_t ) = @_; - $t ||= .20; - $max_t ||= 30; - - my $slept = 0; - while ( $slept <= $max_t ) { - return 1 if $code->(); - PTDEVDEBUG && _d('wait_until sleeping', $t); - sleep $t; - $slept += $t; - PTDEVDEBUG && _d('wait_until slept', $slept, 'of', $max_t); - } - return 0; -} - -# Wait t seconds for code to return. -sub wait_for { - my ( $code, $t ) = @_; - $t ||= 0; - my $mask = POSIX::SigSet->new(&POSIX::SIGALRM); - my $action = POSIX::SigAction->new( - sub { die }, - $mask, - ); - my $oldaction = POSIX::SigAction->new(); - sigaction(&POSIX::SIGALRM, $action, $oldaction); - eval { - alarm $t; - $code->(); - alarm 0; - }; - if ( $EVAL_ERROR ) { - # alarm was raised - return 1; - } - return 0; -} - -sub wait_for_table { - my ($dbh, $tbl, $where) = @_; - my $sql = "SELECT 1 FROM $tbl" . ($where ? " WHERE $where LIMIT 1" : ""); - return wait_until( - sub { - my $r; - eval { $r = $dbh->selectrow_arrayref($sql); }; - if ( $EVAL_ERROR ) { - PTDEVDEBUG && _d('Waiting on', $dbh, 'for table', $tbl, - 'error:', $EVAL_ERROR); - return 0; - } - if ( $where && (!$r || !scalar @$r) ) { - PTDEVDEBUG && _d('Waiting on', $dbh, 'for table', $tbl, - 'WHERE', $where); - return 0; - } - return 1; - }, - ); -} - -sub wait_for_files { - my (@files) = @_; - return wait_until( - sub { - foreach my $file (@files) { - if ( ! -f $file ) { - PTDEVDEBUG && _d('Waiting for file', $file); - return 0; - } - } - return 1; - }, - ); -} - -sub wait_for_sh { - my ($cmd) = @_; - return wait_until( - sub { - my $retval = system("$cmd 2>/dev/null"); - return $retval >> 8 == 0 ? 1 : 0; - } - ); -}; - -sub not_running { - my ($cmd) = @_; - PTDEVDEBUG && _d('Wait until not running:', $cmd); - return wait_until( - sub { - my $output = `ps x | grep -v grep | grep "$cmd"`; - PTDEVDEBUG && _d($output); - return 1 unless $output; - return 0; - } - ); -} - -sub _read { - my ( $fh ) = @_; - return <$fh>; -} - -sub test_log_parser { - my ( %args ) = @_; - foreach my $arg ( qw(parser file) ) { - die "I need a $arg argument" unless $args{$arg}; - } - my $p = $args{parser}; - - # Make sure caller isn't giving us something we don't understand. - # We could ignore it, but then caller might not get the results - # they expected. - map { die "What is $_ for?"; } - grep { $_ !~ m/^(?:parser|misc|file|result|num_events|oktorun)$/ } - keys %args; - - my $file = "$trunk/$args{file}"; - my @e; - eval { - open my $fh, "<", $file or die "Cannot open $file: $OS_ERROR"; - my %parser_args = ( - next_event => sub { return _read($fh); }, - tell => sub { return tell($fh); }, - fh => $fh, - misc => $args{misc}, - oktorun => $args{oktorun}, - ); - while ( my $e = $p->parse_event(%parser_args) ) { - push @e, $e; - } - close $fh; - }; - - my ($base_file_name) = $args{file} =~ m/([^\/]+)$/; - is( - $EVAL_ERROR, - '', - "$base_file_name: no errors" - ); - - if ( defined $args{result} ) { - is_deeply( - \@e, - $args{result}, - "$base_file_name: results" - ) or diag(Dumper(\@e)); - } - - if ( defined $args{num_events} ) { - is( - scalar @e, - $args{num_events}, - "$base_file_name: $args{num_events} events" - ); - } - - return \@e; -} - -sub test_protocol_parser { - my ( %args ) = @_; - foreach my $arg ( qw(parser protocol file) ) { - die "I need a $arg argument" unless $args{$arg}; - } - my $parser = $args{parser}; - my $protocol = $args{protocol}; - - # Make sure caller isn't giving us something we don't understand. - # We could ignore it, but then caller might not get the results - # they expected. - map { die "What is $_ for?"; } - grep { $_ !~ m/^(?:parser|protocol|misc|file|result|num_events|desc)$/ } - keys %args; - - my $file = "$trunk/$args{file}"; - my @e; - eval { - open my $fh, "<", $file or die "Cannot open $file: $OS_ERROR"; - my %parser_args = ( - next_event => sub { return _read($fh); }, - tell => sub { return tell($fh); }, - misc => $args{misc}, - ); - while ( my $p = $parser->parse_event(%parser_args) ) { - my $e = $protocol->parse_event(%parser_args, event => $p); - push @e, $e if $e; - } - close $fh; - }; - - my ($base_file_name) = $args{file} =~ m/([^\/]+)$/; - is( - $EVAL_ERROR, - '', - "$base_file_name: no errors" - ); - - if ( defined $args{result} ) { - is_deeply( - \@e, - $args{result}, - "$base_file_name: " . ($args{desc} || "results") - ) or diag(Dumper(\@e)); - } - - if ( defined $args{num_events} ) { - is( - scalar @e, - $args{num_events}, - "$base_file_name: $args{num_events} events" - ); - } - - return \@e; -} - -sub test_packet_parser { - my ( %args ) = @_; - foreach my $arg ( qw(parser file) ) { - die "I need a $arg argument" unless $args{$arg}; - } - my $parser = $args{parser}; - - # Make sure caller isn't giving us something we don't understand. - # We could ignore it, but then caller might not get the results - # they expected. - map { die "What is $_ for?"; } - grep { $_ !~ m/^(?:parser|misc|file|result|desc|oktorun)$/ } - keys %args; - - my $file = "$trunk/$args{file}"; - my @packets; - open my $fh, '<', $file or die "Cannot open $file: $OS_ERROR"; - my %parser_args = ( - next_event => sub { return _read($fh); }, - tell => sub { return tell($fh); }, - misc => $args{misc}, - oktorun => $args{oktorun}, - ); - while ( my $packet = $parser->parse_event(%parser_args) ) { - push @packets, $packet; - } - - # raw_packet is the actual dump text from the file. It's used - # in MySQLProtocolParser but I don't think we need to double-check - # it here. It will make the results very long. - foreach my $packet ( @packets ) { - delete $packet->{raw_packet}; - } - - if ( !is_deeply( - \@packets, - $args{result}, - "$args{file}" . ($args{desc} ? ": $args{desc}" : '') - ) ) { - diag(Dumper(\@packets)); - } - - return; -} - -# no_diff() compares the STDOUT output of a cmd or code to expected output. -# Returns true if there are no differences between the two outputs, -# else returns false. Dies if the cmd/code dies. Does not capture STDERR. -# Args: -# * cmd scalar or coderef: if cmd is a scalar then the -# cmd is ran via the shell. if it's a coderef then -# the code is ran. the latter is preferred because -# it generates test coverage. -# * expected_output scalar: file name relative to PERCONA_TOOLKIT_BRANCH -# * args hash: (optional) may include -# update_sample overwrite expected_output with cmd/code output -# keep_output keep last cmd/code output file -# transform_result transform the code to be compared but do not -# reflect these changes on the original file -# if update_sample is passed in -# transform_sample similar to the above, but with the sample -# file -# * trf transform cmd/code output before diff -# The sub dies if cmd or code dies. STDERR is not captured. -sub no_diff { - my ( $cmd, $expected_output, %args ) = @_; - die "I need a cmd argument" unless $cmd; - die "I need an expected_output argument" unless $expected_output; - - die "$expected_output does not exist" unless -f "$trunk/$expected_output"; - $expected_output = "$trunk/$expected_output"; - - my $tmp_file = '/tmp/percona-toolkit-test-output.txt'; - my $tmp_file_orig = '/tmp/percona-toolkit-test-output-original.txt'; - - if ( my $sed_args = $args{sed_out} ) { - `cat $expected_output | sed $sed_args > /tmp/pt-test-outfile-trf`; - $expected_output = "/tmp/pt-test-outfile-trf"; - } - - # Determine cmd type and run it. - if ( ref $cmd eq 'CODE' ) { - output($cmd, file => $tmp_file); - } - elsif ( $args{cmd_output} ) { - # Copy cmd output to tmp file so we don't with the original. - open my $tmp_fh, '>', $tmp_file or die "Cannot open $tmp_file: $OS_ERROR"; - print $tmp_fh $cmd; - close $tmp_fh; - } - else { - `$cmd > $tmp_file`; - } - - # Do optional arg stuff. - `cp $tmp_file $tmp_file_orig`; - if ( my $trf = $args{trf} ) { - `$trf $tmp_file_orig > $tmp_file`; - } - if ( my $post_pipe = $args{post_pipe} ) { - `cat $tmp_file | $post_pipe > $tmp_file-2`; - `mv $tmp_file-2 $tmp_file`; - } - if ( my $sed_args = $args{sed} ) { - foreach my $sed_args ( @{$args{sed}} ) { - `cat $tmp_file | sed $sed_args > $tmp_file-2`; - `mv $tmp_file-2 $tmp_file`; - } - } - if ( defined(my $sort_args = $args{sort}) ) { - `cat $tmp_file | sort $sort_args > $tmp_file-2`; - `mv $tmp_file-2 $tmp_file`; - } - - my $res_file = $tmp_file; - if ( $args{transform_result} ) { - (undef, $res_file) = tempfile(); - output( - sub { $args{transform_result}->($tmp_file) }, - file => $res_file, - ); - } - - my $cmp_file = $expected_output; - if ( $args{transform_sample} ) { - (undef, $cmp_file) = tempfile(); - output( - sub { $args{transform_sample}->($expected_output) }, - file => $cmp_file, - ); - } - - # diff the outputs. - my $out = `diff $res_file $cmp_file`; - my $retval = $?; - - # diff returns 0 if there were no differences, - # so !0 = 1 = no diff in our testing parlance. - $retval = $retval >> 8; - - if ( $retval ) { - diag($out); - if ( $ENV{UPDATE_SAMPLES} || $args{update_sample} ) { - `cat $tmp_file > $expected_output`; - diag("Updated $expected_output"); - } - } - - # Remove our tmp files. - `rm -f $tmp_file $tmp_file_orig /tmp/pt-test-outfile-trf >/dev/null 2>&1` - unless $ENV{KEEP_OUTPUT} || $args{keep_output}; - - if ( $res_file ne $tmp_file ) { - 1 while unlink $res_file; - } - - if ( $cmp_file ne $expected_output ) { - 1 while unlink $cmp_file; - } - - return !$retval; -} - -sub throws_ok { - my ( $code, $pat, $msg ) = @_; - eval { $code->(); }; - like ( $EVAL_ERROR, $pat, $msg ); -} - -# Remove /*percona-toolkit ...*/ trace comments from the given SQL statement(s). -# Traces are added in ChangeHandler::process_rows(). -sub remove_traces { - my ( $sql ) = @_; - my $trace_pat = qr/ \/\*percona-toolkit .+?\*\//; - if ( ref $sql && ref $sql eq 'ARRAY' ) { - map { $_ =~ s/$trace_pat//gm } @$sql; - } - else { - $sql =~ s/$trace_pat//gm; - } - return $sql; -} - -sub test_bash_tool { - my ( $tool ) = @_; - die "I need a tool argument" unless $tool; - my $outfile = "/tmp/$tool-test-results.txt"; - `rm -rf $outfile >/dev/null`; - `$trunk/util/test-bash-tool $tool > $outfile`; - print `cat $outfile`; - return; -} - -my %checksum_result_col = ( - ts => 0, - errors => 1, - diffs => 2, - rows => 3, - diff_rows => 4, - chunks => 5, - skipped => 5, - time => 6, - table => 7, -); -sub count_checksum_results { - my ($output, $column, $table) = @_; - - my (@res) = map { - my $line = $_; - my (@cols) = $line =~ m/(\S+)/g; - \@cols; - } - grep { - my $line = $_; - if ( !$table ) { - $line; - } - else { - $line =~ m/$table$/m ? $line : ''; - } - } - grep { m/^\d+\-\d+T\d\d:\d\d:\d\d\s+\d+/ } split /\n/, $output; - my $colno = $checksum_result_col{lc $column}; - die "Invalid checksum result column: $column" unless defined $colno; - my $total = 0; - map { $total += $_->[$colno] } @res; - return $total; -} - -sub normalize_checksum_results { - my ($output) = @_; - my $tmp_file = "/tmp/test-checksum-results-output"; - open my $fh, ">", $tmp_file or die "Cannot open $tmp_file: $OS_ERROR"; - printf $fh $output; - close $fh; - my $normal_output = `cat $tmp_file | awk '/^[0-9 ]/ {print \$2 " " \$3 " " \$4 " " \$5 " " \$6 " " \$7 " " \$9} /^[A-Z]/ {print \$0}'`; - `rm $tmp_file >/dev/null`; - return $normal_output; -} - -sub get_source_binlog_pos { - my ($dbh) = @_; - - my $vp = VersionParser->new($dbh); - my $source_name = 'source'; - if ( $vp->cmp('8.1') < 0 || $vp->flavor() =~ m/maria/i ) { - $source_name = 'master'; - } - - my $sql = "SHOW ${source_name} STATUS"; - my $ms = $dbh->selectrow_hashref($sql); - return $ms->{position}; -} - -sub get_slave_pos_relative_to_source { - my ($dbh) = @_; - my $sql = "SHOW SLAVE STATUS"; - my $ss = $dbh->selectrow_hashref($sql); - return $ss->{exec_source_log_pos}; -} - -# Like output(), but forks a process to execute the coderef. -# This is because otherwise, errors thrown during cleanup -# would be skipped. -sub full_output { - my ( $code, %args ) = @_; - die "I need a code argument" unless $code; - - local (*STDOUT, *STDERR); - require IO::File; - - my (undef, $file) = tempfile(); - open *STDOUT, '>', $file - or die "Cannot open file $file: $OS_ERROR"; - *STDOUT->autoflush(1); - - my (undef, $file2) = tempfile(); - open *STDERR, '>', $file2 - or die "Cannot open file $file2: $OS_ERROR"; - *STDERR->autoflush(1); - - my $status; - if (my $pid = fork) { - if ( my $t = $args{wait_for} ) { - # Wait for t seconds then kill the child. - sleep $t; - my $tries = 3; - # Most tools require 2 interrupts to make them stop. - while ( kill(0, $pid) && $tries-- ) { - kill SIGTERM, $pid; - sleep 0.10; - } - # Child didn't respond to SIGTERM? Then kill -9 it. - kill SIGKILL, $pid if kill(0, $pid); - sleep 0.25; - } - waitpid($pid, 0); - $status = $? >> 8; - } - else { - exit $code->(); - } - close $_ or die "Cannot close $_: $OS_ERROR" for qw(STDOUT STDERR); - my $output = slurp_file($file) . slurp_file($file2); - - unlink $file; - unlink $file2; - - return ($output, $status); -} - -sub tables_used { - my ($file) = @_; - local $INPUT_RECORD_SEPARATOR = ''; - open my $fh, '<', $file or die "Cannot open $file: $OS_ERROR"; - my %tables; - while ( defined(my $chunk = <$fh>) ) { - map { - my $db_tbl = $_; - $db_tbl =~ s/^\s*`?//; # strip leading space and ` - $db_tbl =~ s/\s*`?$//; # strip trailing space and ` - $db_tbl =~ s/`\.`/./; # strip inner `.` - $tables{$db_tbl} = 1; - } - grep { - m/(?:\w\.\w|`\.`)/ # only db.tbl, not just db - } - $chunk =~ m/(?:FROM|INTO|UPDATE)\s+(\S+)/gi; - } - return [ sort keys %tables ]; -} - -sub can_load_data { - my $output = `/tmp/12345/use -e "SELECT * FROM percona_test.load_data" 2>/dev/null`; - return ($output || '') =~ /1/; -} - -sub _d { - my ($package, undef, $line) = caller 0; - @_ = map { (my $temp = $_) =~ s/\n/\n# /g; $temp; } - map { defined $_ ? $_ : 'undef' } - @_; - print STDERR "# $package:$line $PID ", join(' ', @_), "\n"; -} - -1; -} -# ########################################################################### -# End PerconaTest package -# ########################################################################### diff --git a/lib/Percona/XtraDB/Cluster.pm b/lib/Percona/XtraDB/Cluster.pm index 4b57bd6e..17c7a0d1 100644 --- a/lib/Percona/XtraDB/Cluster.pm +++ b/lib/Percona/XtraDB/Cluster.pm @@ -190,31 +190,31 @@ sub autodetect_nodes { seen_ids => $seen_ids ); - my $new_slaves = []; + my $new_replicas = []; foreach my $node (@$new_nodes) { - my $node_slaves = $ms->get_slaves( + my $node_replicas = $ms->get_replicas( dbh => $node->dbh(), dsn => $node->dsn(), make_cxn => $make_cxn, ); - push @$new_slaves, @$node_slaves; + push @$new_replicas, @$node_replicas; } - $new_slaves = $self->remove_duplicate_cxns( - cxns => $new_slaves, + $new_replicas = $self->remove_duplicate_cxns( + cxns => $new_replicas, seen_ids => $seen_ids ); - # If some of the new slaves is a cluster node, autodetect new nodes + # If some of the new replicas is a cluster node, autodetect new nodes # from there too. - my @new_slave_nodes = grep { $self->is_cluster_node($_) } @$new_slaves; + my @new_replica_nodes = grep { $self->is_cluster_node($_) } @$new_replicas; - my $slaves_of_slaves = $self->autodetect_nodes( + my $replicas_of_replicas = $self->autodetect_nodes( %args, - nodes => \@new_slave_nodes, + nodes => \@new_replica_nodes, ); - my @autodetected_nodes = ( @$new_nodes, @$new_slaves, @$slaves_of_slaves ); + my @autodetected_nodes = ( @$new_nodes, @$new_replicas, @$replicas_of_replicas ); return \@autodetected_nodes; } diff --git a/lib/PerconaTest.pm b/lib/PerconaTest.pm index d86399d8..3a211672 100644 --- a/lib/PerconaTest.pm +++ b/lib/PerconaTest.pm @@ -54,7 +54,7 @@ our @EXPORT = qw( parse_file wait_until wait_for - wait_until_slave_running + wait_until_replica_running test_log_parser test_protocol_parser test_packet_parser @@ -774,7 +774,7 @@ sub get_source_binlog_pos { return $ms->{position}; } -sub get_slave_pos_relative_to_source { +sub get_replica_pos_relative_to_source { my ($dbh) = @_; my $vp = VersionParser->new($dbh); diff --git a/lib/QueryRewriter.pm b/lib/QueryRewriter.pm index c92dccd2..e8ae6a18 100644 --- a/lib/QueryRewriter.pm +++ b/lib/QueryRewriter.pm @@ -274,7 +274,7 @@ sub distill_verbs { $query = $self->strip_comments($query); # SHOW statements are either 2 or 3 words: SHOW A (B), where A and B - # are words; B is optional. E.g. "SHOW TABLES" or "SHOW SLAVE STATUS". + # are words; B is optional. E.g. "SHOW TABLES" or "SHOW REPLICA STATUS". # There's a few common keywords that may show up in place of A, so we # remove them first. Then there's some keywords that signify extra clauses # that may show up in place of B and since these clauses are at the diff --git a/lib/ReplicaLagWaiter.pm b/lib/ReplicaLagWaiter.pm index 47cec684..c5e24d17 100644 --- a/lib/ReplicaLagWaiter.pm +++ b/lib/ReplicaLagWaiter.pm @@ -19,7 +19,7 @@ # ########################################################################### { # Package: ReplicaLagWaiter -# ReplicaLagWaiter helps limit slave lag when working on the source. +# ReplicaLagWaiter helps limit replica lag when working on the source. package ReplicaLagWaiter; use strict; @@ -34,16 +34,16 @@ use Data::Dumper; # # Required Arguments: # oktorun - Callback that returns true if it's ok to continue running -# get_lag - Callback passed slave dbh and returns slave's lag +# get_lag - Callback passed replica dbh and returns replica's lag # sleep - Callback to sleep between checking lag. # max_lag - Max lag -# slaves - Arrayref of objects +# replicas - Arrayref of objects # # Returns: # ReplicaLagWaiter object sub new { my ( $class, %args ) = @_; - my @required_args = qw(oktorun get_lag sleep max_lag slaves); + my @required_args = qw(oktorun get_lag sleep max_lag replicas); foreach my $arg ( @required_args ) { die "I need a $arg argument" unless defined $args{$arg}; } @@ -56,13 +56,13 @@ sub new { } # Sub: wait -# Wait for Seconds_Behind_Source on all slaves to become < max. +# Wait for Seconds_Behind_Source on all replicas to become < max. # # Optional Arguments: # Progress - object to report waiting # # Returns: -# 1 if all slaves catch up before timeout, else 0 if continue=yes, else die. +# 1 if all replicas catch up before timeout, else 0 if continue=yes, else die. sub wait { my ( $self, %args ) = @_; my @required_args = qw(); @@ -71,34 +71,34 @@ sub wait { } my $pr = $args{Progress}; - my $oktorun = $self->{oktorun}; - my $get_lag = $self->{get_lag}; - my $sleep = $self->{sleep}; - my $slaves = $self->{slaves}; - my $max_lag = $self->{max_lag}; + my $oktorun = $self->{oktorun}; + my $get_lag = $self->{get_lag}; + my $sleep = $self->{sleep}; + my $replicas = $self->{replicas}; + my $max_lag = $self->{max_lag}; - my $worst; # most lagging slave + my $worst; # most lagging replica my $pr_callback; my $pr_first_report; - ### refresh list of slaves. In: self passed to wait() - ### Returns: new slave list - my $pr_refresh_slave_list = sub { + ### refresh list of replicas. In: self passed to wait() + ### Returns: new replica list + my $pr_refresh_replica_list = sub { my ($self) = @_; - my ($slaves, $refresher) = ($self->{slaves}, $self->{get_slaves_cb}); - return $slaves if ( not defined $refresher ); - my $before = join ' ', sort map {$_->description()} @$slaves; - $slaves = $refresher->(); - my $after = join ' ', sort map {$_->description()} @$slaves; + my ($replicas, $refresher) = ($self->{replicas}, $self->{get_replicas_cb}); + return $replicas if ( not defined $refresher ); + my $before = join ' ', sort map {$_->description()} @$replicas; + $replicas = $refresher->(); + my $after = join ' ', sort map {$_->description()} @$replicas; if ($before ne $after) { - $self->{slaves} = $slaves; - printf STDERR "Slave set to watch has changed\n Was: %s\n Now: %s\n", + $self->{replicas} = $replicas; + printf STDERR "Replica set to watch has changed\n Was: %s\n Now: %s\n", $before, $after; } - return($self->{slaves}); + return($self->{replicas}); }; - $slaves = $pr_refresh_slave_list->($self); + $replicas = $pr_refresh_replica_list->($self); if ( $pr ) { # If you use the default Progress report callback, you'll need to @@ -136,54 +136,54 @@ sub wait { }; } - # First check all slaves. - my @lagged_slaves = map { {cxn=>$_, lag=>undef} } @$slaves; - while ( $oktorun->() && @lagged_slaves ) { - PTDEBUG && _d('Checking slave lag'); + # First check all replicas. + my @lagged_replicas = map { {cxn=>$_, lag=>undef} } @$replicas; + while ( $oktorun->() && @lagged_replicas ) { + PTDEBUG && _d('Checking replica lag'); - ### while we were waiting our list of slaves may have changed - $slaves = $pr_refresh_slave_list->($self); + ### while we were waiting our list of replicas may have changed + $replicas = $pr_refresh_replica_list->($self); my $watched = 0; - @lagged_slaves = grep { - my $slave_name = $_->{cxn}->name(); - grep {$slave_name eq $_->name()} @{$slaves // []} - } @lagged_slaves; + @lagged_replicas = grep { + my $replica_name = $_->{cxn}->name(); + grep {$replica_name eq $_->name()} @{$replicas // []} + } @lagged_replicas; - for my $i ( 0..$#lagged_slaves ) { + for my $i ( 0..$#lagged_replicas ) { my $lag; eval { - $lag = $get_lag->($lagged_slaves[$i]->{cxn}); + $lag = $get_lag->($lagged_replicas[$i]->{cxn}); }; if ($EVAL_ERROR) { die $EVAL_ERROR; } - PTDEBUG && _d($lagged_slaves[$i]->{cxn}->name(), - 'slave lag:', $lag); + PTDEBUG && _d($lagged_replicas[$i]->{cxn}->name(), + 'replica lag:', $lag); if ( !defined $lag || $lag > $max_lag ) { - $lagged_slaves[$i]->{lag} = $lag; + $lagged_replicas[$i]->{lag} = $lag; } else { - delete $lagged_slaves[$i]; + delete $lagged_replicas[$i]; } } - # Remove slaves that aren't lagging. - @lagged_slaves = grep { defined $_ } @lagged_slaves; - if ( @lagged_slaves ) { - # Sort lag, undef is highest because it means the slave is stopped. - @lagged_slaves = reverse sort { + # Remove replicas that aren't lagging. + @lagged_replicas = grep { defined $_ } @lagged_replicas; + if ( @lagged_replicas ) { + # Sort lag, undef is highest because it means the replica is stopped. + @lagged_replicas = reverse sort { defined $a->{lag} && defined $b->{lag} ? $a->{lag} <=> $b->{lag} : defined $a->{lag} ? -1 : 1; - } @lagged_slaves; - $worst = $lagged_slaves[0]; - PTDEBUG && _d(scalar @lagged_slaves, 'slaves are lagging, worst:', + } @lagged_replicas; + $worst = $lagged_replicas[0]; + PTDEBUG && _d(scalar @lagged_replicas, 'replicas are lagging, worst:', $worst->{lag}, 'on', Dumper($worst->{cxn}->dsn())); if ( $pr ) { # There's no real progress because we can't estimate how long - # it will take all slaves to catch up. The progress reports - # are just to inform the user every 30s which slave is still + # it will take all replicas to catch up. The progress reports + # are just to inform the user every 30s which replica is still # lagging this most. $pr->update( sub { return 0; }, @@ -196,7 +196,7 @@ sub wait { } } - PTDEBUG && _d('All slaves caught up'); + PTDEBUG && _d('All replicas caught up'); return; } diff --git a/lib/Safeguards.pm b/lib/Safeguards.pm deleted file mode 100644 index 1cee49af..00000000 --- a/lib/Safeguards.pm +++ /dev/null @@ -1,94 +0,0 @@ -# This program is copyright 2013 Percona Ireland Ltd. -# Feedback and improvements are welcome. -# -# THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED -# WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF -# MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. -# -# This program is free software; you can redistribute it and/or modify it under -# the terms of the GNU General Public License as published by the Free Software -# Foundation, version 2; OR the Perl Artistic License. On UNIX and similar -# systems, you can issue `man perlgpl' or `man perlartistic' to read these -# licenses. -# -# You should have received a copy of the GNU General Public License along with -# this program; if not, write to the Free Software Foundation, Inc., 59 Temple -# Place, Suite 330, Boston, MA 02111-1307 USA. -# ########################################################################### -# Safeguards package -# ########################################################################### -package Safeguards; - -use strict; -use warnings FATAL => 'all'; -use English qw(-no_match_vars); - -use constant PTDEBUG => $ENV{PTDEBUG} || 0; - -sub new { - my ($class, %args) = @_; - my $self = { - disk_bytes_free => $args{disk_bytes_free} || 104857600, # 100 MiB - disk_pct_free => $args{disk_pct_free} || 5, - }; - return bless $self, $class; -} - -sub get_disk_space { - my ($self, %args) = @_; - my $filesystem = $args{filesystem} || $ENV{PWD}; - - # Filesystem 1024-blocks Used Available Capacity Mounted on - # /dev/disk0s2 118153176 94409664 23487512 81% / - my $disk_space = `df -P -k "$filesystem"`; - chop($disk_space) if $disk_space; - PTDEBUG && _d('Disk space on', $filesystem, $disk_space); - - return $disk_space; -} - -sub check_disk_space() { - my ($self, %args) = @_; - my $disk_space = $args{disk_space}; - PTDEBUG && _d("Checking disk space:\n", $disk_space); - - # There may be other info, so extract just the partition line, - # i.e. the first line starting with /, as in: - # Filesystem 1024-blocks Used Available Capacity Mounted on - # /dev/disk0s2 118153176 94409664 23487512 81% / - my ($partition) = $disk_space =~ m/^\s*(\/.+)/m; - PTDEBUG && _d('Partition:', $partition); - die "Failed to parse partition from disk space:\n$disk_space" - unless $partition; - - # Parse the partition line. - my (undef, undef, $bytes_used, $bytes_free, $pct_used, undef) - = $partition =~ m/(\S+)/g; - PTDEBUG && _d('Bytes used:', $bytes_used, 'free:', $bytes_free, - 'Percentage used:', $pct_used); - - # Convert 1024-blocks blocks to bytes. - $bytes_used = ($bytes_used || 0) * 1024; - $bytes_free = ($bytes_free || 0) * 1024; - - # Convert pct used to free. - $pct_used =~ s/%//; - my $pct_free = 100 - ($pct_used || 0); - - # Return true if both thresholds are ok. - return $bytes_free >= $self->{disk_bytes_free} - && $pct_free >= $self->{disk_pct_free}; -} - -sub _d { - my ($package, undef, $line) = caller 0; - @_ = map { (my $temp = $_) =~ s/\n/\n# /g; $temp; } - map { defined $_ ? $_ : 'undef' } - @_; - print STDERR "# $package:$line $PID ", join(' ', @_), "\n"; -} - -1; -# ########################################################################### -# End Safeguards package -# ########################################################################### diff --git a/lib/Sandbox.pm b/lib/Sandbox.pm index 24403b1c..93c2a205 100644 --- a/lib/Sandbox.pm +++ b/lib/Sandbox.pm @@ -171,7 +171,7 @@ sub load_file { if ( $? >> 8 ) { die "Failed to execute $file on $server: $out"; } - $self->wait_for_slaves() unless $args{no_wait}; + $self->wait_for_replicas() unless $args{no_wait}; } sub _use_for { @@ -211,7 +211,7 @@ sub wipe_clean { $dbh->do("DROP DATABASE IF EXISTS `$db`"); } - $self->wait_for_slaves(); + $self->wait_for_replicas(); $self->clear_genlogs(); return; @@ -229,18 +229,18 @@ sub source_is_ok { } # Returns a string if there is a problem with the replica. -sub slave_is_ok { - my ($self, $slave, $source, $ro) = @_; - return if $self->is_cluster_node($slave); - PTDEBUG && _d('Checking if replica', $slave, $port_for{$slave}, +sub replica_is_ok { + my ($self, $replica, $source, $ro) = @_; + return if $self->is_cluster_node($replica); + PTDEBUG && _d('Checking if replica', $replica, $port_for{$replica}, 'to', $source, $port_for{$source}, 'is ok'); - my $slave_dbh = $self->get_dbh_for($slave); - if ( !$slave_dbh ) { - return "Sandbox $slave " . $port_for{$slave} . " is down."; + my $replica_dbh = $self->get_dbh_for($replica); + if ( !$replica_dbh ) { + return "Sandbox $replica " . $port_for{$replica} . " is down."; } - my $vp = VersionParser->new($slave_dbh); + my $vp = VersionParser->new($replica_dbh); my $replica_name = 'replica'; my $source_name = 'source'; if ( $vp->cmp('8.1') < 0 || $vp->flavor() =~ m/maria/i ) { @@ -248,31 +248,31 @@ sub slave_is_ok { $source_name = 'master'; } my $source_port = $port_for{$source}; - my $status = $slave_dbh->selectall_arrayref( + my $status = $replica_dbh->selectall_arrayref( "SHOW ${replica_name} STATUS", { Slice => {} }); if ( !$status || !@$status ) { - return "Sandbox $slave " . $port_for{$slave} . " is not a replica."; + return "Sandbox $replica " . $port_for{$replica} . " is not a replica."; } if ( $status->[0]->{last_error} ) { warn Dumper($status); - return "Sandbox $slave " . $port_for{$slave} . " is broken: " + return "Sandbox $replica " . $port_for{$replica} . " is broken: " . $status->[0]->{last_error} . "."; } foreach my $thd ( "${replica_name}_io_running", "${replica_name}_sql_running" ) { if ( ($status->[0]->{$thd} || 'No') eq 'No' ) { warn Dumper($status); - return "Sandbox $slave " . $port_for{$slave} . " $thd thread " + return "Sandbox $replica " . $port_for{$replica} . " $thd thread " . "is not running."; } } if ( $ro ) { - my $row = $slave_dbh->selectrow_arrayref( + my $row = $replica_dbh->selectrow_arrayref( "SHOW VARIABLES LIKE 'read_only'"); if ( !$row || $row->[1] ne 'ON' ) { - return "Sandbox $slave " . $port_for{$slave} . " is not read-only."; + return "Sandbox $replica " . $port_for{$replica} . " is not read-only."; } } @@ -283,16 +283,16 @@ sub slave_is_ok { PTDEBUG && _d('Replica lag:', $status->[0]->{"seconds_behind_${source_name}"}); sleep $sleep_t; $total_t += $sleep_t; - $status = $slave_dbh->selectall_arrayref( + $status = $replica_dbh->selectall_arrayref( "SHOW ${replica_name} STATUS", { Slice => {} }); if ( $total_t == 5 ) { - Test::More::diag("Waiting for sandbox $slave " . $port_for{$slave} + Test::More::diag("Waiting for sandbox $replica " . $port_for{$replica} . " to catch up..."); } } - PTDEBUG && _d('Slave', $slave, $port_for{$slave}, 'is ok'); - $slave_dbh->disconnect(); + PTDEBUG && _d('Replica', $replica, $port_for{$replica}, 'is ok'); + $replica_dbh->disconnect(); return; } @@ -331,10 +331,10 @@ sub ok { my ($self) = @_; my @errors; # First, wait for all replicas to be caught up to their sources. - $self->wait_for_slaves(); + $self->wait_for_replicas(); push @errors, $self->source_is_ok('source'); - push @errors, $self->slave_is_ok('replica1', 'source'); - push @errors, $self->slave_is_ok('replica2', 'replica1', 1); + push @errors, $self->replica_is_ok('replica1', 'source'); + push @errors, $self->replica_is_ok('replica2', 'replica1', 1); push @errors, $self->leftover_servers(); foreach my $host ( qw(source replica1 replica2) ) { push @errors, $self->leftover_databases($host); @@ -346,16 +346,16 @@ sub ok { } # Dings a heartbeat on the source, and waits until the replica catches up fully. -sub wait_for_slaves { +sub wait_for_replicas { my ($self, %args) = @_; my $source_dbh = $self->get_dbh_for($args{source} || 'source'); - my $slave2_dbh = $self->get_dbh_for($args{replica} || 'replica2'); + my $replica2_dbh = $self->get_dbh_for($args{replica} || 'replica2'); my ($ping) = $source_dbh->selectrow_array("SELECT MD5(RAND())"); - $source_dbh->do("UPDATE percona_test.sentinel SET ping='$ping' WHERE id=1 /* wait_for_slaves */"); + $source_dbh->do("UPDATE percona_test.sentinel SET ping='$ping' WHERE id=1 /* wait_for_replicas */"); PerconaTest::wait_until( sub { - my ($pong) = $slave2_dbh->selectrow_array( - "SELECT ping FROM percona_test.sentinel WHERE id=1 /* wait_for_slaves */"); + my ($pong) = $replica2_dbh->selectrow_array( + "SELECT ping FROM percona_test.sentinel WHERE id=1 /* wait_for_replicas */"); return $ping eq ($pong || ''); }, undef, 300 ); @@ -469,7 +469,7 @@ sub can_load_data { return ($output || '') =~ /1/; } -sub set_as_slave { +sub set_as_replica { my ($self, $server, $source_server, @extras) = @_; PTDEBUG && _d("Setting $server as replica of $source_server"); diff --git a/lib/TableSyncer.pm b/lib/TableSyncer.pm index 7c2cd519..8fb10b79 100644 --- a/lib/TableSyncer.pm +++ b/lib/TableSyncer.pm @@ -255,12 +255,12 @@ sub sync_table { $dst_sql .= ' FOR UPDATE'; } elsif ( $args{changing_src} ) { - # Making changes on source (src) which replicate to slave (dst). + # Making changes on source (src) which replicate to replica (dst). $src_sql .= ' FOR UPDATE'; $dst_sql .= ' LOCK IN SHARE MODE'; } else { - # Making changes on slave (dst). + # Making changes on replica (dst). $src_sql .= ' LOCK IN SHARE MODE'; $dst_sql .= ' FOR UPDATE'; } @@ -449,7 +449,7 @@ sub unlock { # 3 => global # This function might actually execute the $src_sth. If we're using # transactions instead of table locks, the $src_sth has to be executed before -# the SOURCE_POS_WAIT() on the slave. The return value is whether the +# the SOURCE_POS_WAIT() on the replica. The return value is whether the # $src_sth was executed. sub lock_and_wait { my ( $self, %args ) = @_; @@ -478,7 +478,7 @@ sub lock_and_wait { } # User wants us to lock for consistency. But lock only on source initially; - # might have to wait for the slave to catch up before locking on the dest. + # might have to wait for the replica to catch up before locking on the dest. if ( $args{lock} == 3 ) { my $sql = 'FLUSH TABLES WITH READ LOCK'; PTDEBUG && _d($src->{dbh}, $sql); @@ -531,32 +531,32 @@ sub lock_and_wait { # $src_sth. $wait = $ms->wait_for_source( source_status => $ms->get_source_status($src->{misc_dbh}), - slave_dbh => $dst->{dbh}, + replica_dbh => $dst->{dbh}, timeout => $timeout, ); if ( defined $wait->{result} && $wait->{result} != -1 ) { - return; # slave caught up + return; # replica caught up } die; # call fail }, fail => sub { my (%args) = @_; if ( !defined $wait->{result} ) { - # Slave was stopped either before or during the wait. + # Replica was stopped either before or during the wait. # Wait a few seconds and try again in hopes that the - # slave is restarted. This is the only case for which - # we wait and retry because the slave might have been + # replica is restarted. This is the only case for which + # we wait and retry because the replica might have been # stopped temporarily and/or unbeknownst to the user, - # so they'll be happy if we wait for slave to be restarted + # so they'll be happy if we wait for replica to be restarted # and then continue syncing. my $msg; if ( $wait->{waited} ) { - $msg = "The slave was stopped while waiting with " + $msg = "The replica was stopped while waiting with " . "SOURCE_POS_WAIT()."; } else { $msg = "SOURCE_POS_WAIT() returned NULL. Verify that " - . "the slave is running."; + . "the replica is running."; } if ( $tries - $args{tryno} ) { $msg .= " Sleeping $sleep seconds then retrying " @@ -572,9 +572,9 @@ sub lock_and_wait { } }, final_fail => sub { - die "Slave did not catch up to its source after $tries attempts " + die "Replica did not catch up to its source after $tries attempts " . "of waiting $timeout seconds with SOURCE_POS_WAIT. " - . "Check that the slave is running, increase the --wait " + . "Check that the replica is running, increase the --wait " . "time, or disable this feature by specifying --wait 0."; }, ); # retry MasterSlave::wait_for_source() diff --git a/lib/VariableAdvisorRules.pm b/lib/VariableAdvisorRules.pm index dcbace9b..5ac4c88d 100644 --- a/lib/VariableAdvisorRules.pm +++ b/lib/VariableAdvisorRules.pm @@ -129,6 +129,13 @@ sub get_rules { return $args{variables}->{init_slave} ? 1 : 0; }, }, + { + id => 'init_replica', + code => sub { + my ( %args ) = @_; + return $args{variables}->{init_replica} ? 1 : 0; + }, + }, { id => 'innodb_additional_mem_pool_size', code => sub { @@ -375,6 +382,13 @@ sub get_rules { return _var_gt($args{variables}->{slave_net_timeout}, 60); }, }, + { + id => 'replica_net_timeout', + code => sub { + my ( %args ) = @_; + return _var_gt($args{variables}->{replica_net_timeout}, 60); + }, + }, { id => 'slave_skip_errors', code => sub { @@ -383,6 +397,14 @@ sub get_rules { && $args{variables}->{slave_skip_errors} ne 'OFF' ? 1 : 0; }, }, + { + id => 'replica_skip_errors', + code => sub { + my ( %args ) = @_; + return $args{variables}->{replica_skip_errors} + && $args{variables}->{replica_skip_errors} ne 'OFF' ? 1 : 0; + }, + }, { id => 'sort_buffer_size-1', code => sub { diff --git a/lib/bash/collect.sh b/lib/bash/collect.sh index 81cf93a3..44b039eb 100644 --- a/lib/bash/collect.sh +++ b/lib/bash/collect.sh @@ -301,7 +301,11 @@ collect_mysql_data_loop() { (echo $ts; ps_prepared_statements "$d/prepared_statements.isrunnning") >> "$d/$p-prepared-statements" & fi - slave_status "$d/$p-slave-status" "${mysql_version}" + local replica_name='replica' + if [ "${mysql_version}" '<' "8.1" ]; then + replica_name="slave" + fi + replica_status "$d/$p-${replica_name}-status" "${mysql_version}" } collect_system_data_loop() { @@ -600,14 +604,13 @@ ps_prepared_statements() { fi } -slave_status() { +replica_status() { local outfile=$1 local mysql_version=$2 + local sql="SHOW REPLICA STATUS\G" if [ "${mysql_version}" '<' "8.1" ]; then - local sql="SHOW SLAVE STATUS\G" - else - local sql="SHOW REPLICA STATUS\G" + sql="SHOW SLAVE STATUS\G" fi echo -e "\n$sql\n" >> $outfile diff --git a/lib/bash/collect_mysql_info.sh b/lib/bash/collect_mysql_info.sh index b2370d68..4b8c065d 100644 --- a/lib/bash/collect_mysql_info.sh +++ b/lib/bash/collect_mysql_info.sh @@ -116,8 +116,10 @@ collect_mysql_plugins () { $CMD_MYSQL $EXT_ARGV -ss -e 'SHOW PLUGINS' 2>/dev/null } -collect_mysql_slave_status () { - $CMD_MYSQL $EXT_ARGV -ssE -e 'SHOW SLAVE STATUS' 2>/dev/null +collect_mysql_replica_status () { + local replica_name="$1" + + $CMD_MYSQL $EXT_ARGV -ssE -e "SHOW ${replica_name} STATUS" 2>/dev/null } collect_mysql_innodb_status () { @@ -146,8 +148,15 @@ collect_mysql_roles () { $CMD_MYSQL $EXT_ARGV -ss -e "$QUERY" 2>/dev/null } -collect_mysql_show_slave_hosts () { - $CMD_MYSQL $EXT_ARGV -ssE -e 'SHOW SLAVE HOSTS' 2>/dev/null +collect_mysql_show_replica_hosts () { + local version="$1" + + local replicas='replicas' + if [ "$version" '<' "8.1" ]; then + replicas='slave hosts' + fi + + $CMD_MYSQL $EXT_ARGV -ssE -e "SHOW ${replicas}" 2>/dev/null } collect_source_logs_status () { @@ -299,7 +308,6 @@ collect_mysql_info () { collect_mysql_status > "$dir/mysql-status" collect_mysql_databases > "$dir/mysql-databases" collect_mysql_plugins > "$dir/mysql-plugins" - collect_mysql_slave_status > "$dir/mysql-slave" collect_mysql_innodb_status > "$dir/innodb-status" collect_mysql_ndb_status > "$dir/ndb-status" collect_mysql_processlist > "$dir/mysql-processlist" @@ -307,11 +315,19 @@ collect_mysql_info () { collect_mysql_roles > "$dir/mysql-roles" collect_keyring_plugins > "$dir/keyring-plugins" + local mysql_version="$(get_var version "$dir/mysql-variables")" + + local replicas='replicas' + local replica_name='replica' + if [ "$mysql_version" '<' "8.1" ]; then + replicas='slave-hosts' + replica_name='slave' + fi + + collect_mysql_replica_status $replica_name > "$dir/mysql-${replica_name}" collect_mysqld_instances "$dir/mysql-variables" > "$dir/mysqld-instances" collect_mysqld_executables "$dir/mysqld-instances" > "$dir/mysqld-executables" - collect_mysql_show_slave_hosts "$dir/mysql-slave-hosts" > "$dir/mysql-slave-hosts" - - local mysql_version="$(get_var version "$dir/mysql-variables")" + collect_mysql_show_replica_hosts "$mysql_version" > "$dir/mysql-${replicas}" local binlog="$(get_var log_bin "$dir/mysql-variables")" if [ "${binlog}" ]; then diff --git a/lib/bash/report_mysql_info.sh b/lib/bash/report_mysql_info.sh index 0f56b724..a2d04390 100644 --- a/lib/bash/report_mysql_info.sh +++ b/lib/bash/report_mysql_info.sh @@ -924,6 +924,7 @@ format_overall_db_stats () { section_percona_server_features () { local file="$1" + replica_name="$2" [ -e "$file" ] || return @@ -952,7 +953,7 @@ section_percona_server_features () { name_val "Enhanced Logging" \ "$(feat_on "$file" log_slow_verbosity ne microtime)" name_val "Replica Perf Logging" \ - "$(feat_on "$file" log_slow_slave_statements)" + "$(feat_on "$file" log_slow_${replica_name}_statements)" # Renamed to query_response_time_stats in 5.5 name_val "Response Time Hist." \ @@ -1108,7 +1109,7 @@ section_noteworthy_variables () { name_val "${v}" "$(shorten $(get_var ${v} "$file") 0)" done for v in log log_error log_warnings log_slow_queries \ - log_queries_not_using_indexes log_slave_updates; + log_queries_not_using_indexes log_${replica_name}_updates; do name_val "${v}" "$(get_var ${v} "$file")" done @@ -1120,6 +1121,7 @@ section_noteworthy_variables () { _semi_sync_stats_for () { local target="$1" local file="$2" + local replica_name="$3" [ -e "$file" ] || return @@ -1147,8 +1149,8 @@ _semi_sync_stats_for () { if [ "${target}" = "source" ] || [ "${target}" = "master" ]; then name_val "${target} timeout in milliseconds" \ "$(get_var "rpl_semi_sync_${target}_timeout" "${file}")" - name_val "${target} waits for slaves" \ - "$(get_var "rpl_semi_sync_${target}_wait_no_slave" "${file}")" + name_val "${target} waits for ${replica_name}s" \ + "$(get_var "rpl_semi_sync_${target}_wait_no_${replica_name}" "${file}")" _d "Prepend Rpl_semi_sync_${target}_ to the following" for v in \ @@ -1182,7 +1184,7 @@ noncounters_pattern () { Not_flushed_delayed_rows Open_files Open_streams Open_tables \ Prepared_stmt_count Qcache_free_blocks Qcache_free_memory \ Qcache_queries_in_cache Qcache_total_blocks Rpl_status \ - Slave_open_temp_tables Slave_running Ssl_cipher Ssl_cipher_list \ + Slave_open_temp_tables Slave_running Replica_open_temp_tables Ssl_cipher Ssl_cipher_list \ Ssl_ctx_verify_depth Ssl_ctx_verify_mode Ssl_default_timeout \ Ssl_session_cache_mode Ssl_session_cache_size Ssl_verify_depth \ Ssl_verify_mode Ssl_version Tc_log_max_pages_used Tc_log_page_size \ @@ -1213,16 +1215,17 @@ section_mysqld () { done < "$executables_file" } -section_slave_hosts () { - local slave_hosts_file="$1" +section_replica_hosts () { + local replica_hosts_file="$1" + local replica_name="$2" - [ -e "$slave_hosts_file" ] || return + [ -e "$replica_hosts_file" ] || return - section "Slave Hosts" - if [ -s "$slave_hosts_file" ]; then - cat "$slave_hosts_file" + section "${replica_name^} Hosts" + if [ -s "$replica_hosts_file" ]; then + cat "$replica_hosts_file" else - echo "No slaves found" + echo "No ${replica_name} found" fi } @@ -1245,6 +1248,7 @@ section_mysql_files () { section_percona_xtradb_cluster () { local mysql_var="$1" local mysql_status="$2" + local replica_name="$3" name_val "Cluster Name" "$(get_var "wsrep_cluster_name" "$mysql_var")" name_val "Cluster Address" "$(get_var "wsrep_cluster_address" "$mysql_var")" @@ -1255,7 +1259,7 @@ section_percona_xtradb_cluster () { name_val "Node Status" "$(get_var "wsrep_cluster_status" "$mysql_status")" name_val "SST Method" "$(get_var "wsrep_sst_method" "$mysql_var")" - name_val "Slave Threads" "$(get_var "wsrep_slave_threads" "$mysql_var")" + name_val "${replica_name^} Threads" "$(get_var "wsrep_${replica_name}_threads" "$mysql_var")" name_val "Ignore Split Brain" "$( parse_wsrep_provider_options "pc.ignore_sb" "$mysql_var" )" name_val "Ignore Quorum" "$( parse_wsrep_provider_options "pc.ignore_quorum" "$mysql_var" )" @@ -1312,6 +1316,27 @@ report_mysql_summary () { # Field width for name_val local NAME_VAL_LEN=25 + # Local variables + local user="$(get_var "pt-summary-internal-user" "$dir/mysql-variables")" + local port="$(get_var port "$dir/mysql-variables")" + local now="$(get_var "pt-summary-internal-now" "$dir/mysql-variables")" + local mysql_version="$(get_var version "$dir/mysql-variables")" + + local source_name='source' + local replica_name='replica' + local source_log='binary' + local source_status='binary log' + local source_logs_file="mysql-binary-logs" + local source_status_file="mysql-binary-log-status" + if [ "${mysql_version}" '<' "8.1" ]; then + source_name='master' + replica_name='slave' + source_log='master' + source_status='master' + source_logs_file='mysql-master-logs' + source_status_file='mysql-master-status' + fi + # ######################################################################## # Header for the whole thing, table of discovered instances # ######################################################################## @@ -1323,27 +1348,10 @@ report_mysql_summary () { section_mysqld "$dir/mysqld-executables" "$dir/mysql-variables" - section_slave_hosts "$dir/mysql-slave-hosts" + section_replica_hosts "$dir/mysql-${replica_name}-hosts" ${replica_name} # ######################################################################## # General date, hostname, etc # ######################################################################## - local user="$(get_var "pt-summary-internal-user" "$dir/mysql-variables")" - local port="$(get_var port "$dir/mysql-variables")" - local now="$(get_var "pt-summary-internal-now" "$dir/mysql-variables")" - local mysql_version="$(get_var version "$dir/mysql-variables")" - - local source_name='source' - local source_log='binary' - local source_status='binary log' - local source_logs_file="mysql-binary-logs" - local source_status_file="mysql-binary-log-status" - if [ "${mysql_version}" '<' "8.1" ]; then - source_name='master' - source_log='master' - source_status='master' - source_logs_file='mysql-master-logs' - source_status_file='mysql-master-status' - fi section "Report On Port ${port}" name_val User "${user}" @@ -1363,10 +1371,10 @@ report_mysql_summary () { local fuzz_procr=$(fuzz $(get_var Threads_running "$dir/mysql-status")) name_val Processes "${fuzz_procs} connected, ${fuzz_procr} running" - local slave="" - if [ -s "$dir/mysql-slave" ]; then slave=""; else slave="not "; fi - local slavecount=$(grep -c 'Binlog Dump' "$dir/mysql-processlist") - name_val Replication "Is ${slave}a slave, has ${slavecount} slaves connected" + local replica="" + if [ -s "$dir/mysql-${replica_name}" ]; then replica=""; else replica="not "; fi + local replicacount=$(grep -c 'Binlog Dump' "$dir/mysql-processlist") + name_val Replication "Is ${replica}a ${replica_name}, has ${replicacount} ${replica_name}s connected" # TODO move this into a section with other files: error log, slow log and @@ -1409,7 +1417,7 @@ report_mysql_summary () { # Percona Server features # ######################################################################## section "Key Percona Server features" - section_percona_server_features "$dir/mysql-variables" + section_percona_server_features "$dir/mysql-variables" "${replica_name}" # ######################################################################## # Percona XtraDB Cluster data @@ -1419,7 +1427,7 @@ report_mysql_summary () { if [ -n "${has_wsrep:-""}" ]; then local wsrep_on="$(feat_on "$dir/mysql-variables" "wsrep_on")" if [ "${wsrep_on:-""}" = "Enabled" ]; then - section_percona_xtradb_cluster "$dir/mysql-variables" "$dir/mysql-status" + section_percona_xtradb_cluster "$dir/mysql-variables" "$dir/mysql-status" "$replica_name" else name_val "wsrep_on" "OFF" fi @@ -1453,13 +1461,13 @@ report_mysql_summary () { if [ "$semisync_enabled_source" = "OFF" -o "$semisync_enabled_source" = "0" -o -z "$semisync_enabled_source" ]; then name_val "Source" "Disabled" else - _semi_sync_stats_for "${source_name}" "$dir/mysql-variables" + _semi_sync_stats_for "${source_name}" "$dir/mysql-variables" "${replica_name}" fi - local semisync_enabled_slave="$(get_var rpl_semi_sync_slave_enabled "$dir/mysql-variables")" - if [ "$semisync_enabled_slave" = "OFF" -o "$semisync_enabled_slave" = "0" -o -z "$semisync_enabled_slave" ]; then - name_val "Slave" "Disabled" + local semisync_enabled_replica="$(get_var rpl_semi_sync_${replica_name}_enabled "$dir/mysql-variables")" + if [ "$semisync_enabled_replica" = "OFF" -o "$semisync_enabled_replica" = "0" -o -z "$semisync_enabled_replica" ]; then + name_val "${replica_name^}" "Disabled" else - _semi_sync_stats_for "slave" "$dir/mysql-variables" + _semi_sync_stats_for "${replica_name}" "$dir/mysql-variables" "${replica_name}" fi fi @@ -1636,8 +1644,8 @@ report_mysql_summary () { format_binlog_filters "$dir/$source_status_file" fi -# Replication: seconds behind, running, filters, skip_slave_start, skip_errors, -# read_only, temp tables open, slave_net_timeout, slave_exec_mode +# Replication: seconds behind, running, filters, skip_replica_start, skip_errors, +# read_only, temp tables open, replica_net_timeout, replica_exec_mode # ######################################################################## # Interesting things that you just ought to know about. diff --git a/t/lib/CompareResults.t b/t/lib/CompareResults.t index 517f8ef9..398b3da4 100644 --- a/t/lib/CompareResults.t +++ b/t/lib/CompareResults.t @@ -655,7 +655,7 @@ EOF $dbh1->do('SET SQL_LOG_BIN=0'); $dbh1->do('insert into test.t3 values (2.0),(3.0)'); $dbh1->do('SET SQL_LOG_BIN=1'); - $sb->wait_for_slaves(); + $sb->wait_for_replicas(); my $left_n_rows = $dbh1->selectcol_arrayref('select count(*) from test.t3')->[0]; my $right_n_rows = $dbh2->selectcol_arrayref('select count(*) from test.t3')->[0]; diff --git a/t/lib/MasterSlave.t b/t/lib/MasterSlave.t index e05856b5..f757b695 100644 --- a/t/lib/MasterSlave.t +++ b/t/lib/MasterSlave.t @@ -26,7 +26,7 @@ my $dp = new DSNParser(opts=>$dsn_opts); my $sb = new Sandbox(basedir => '/tmp', DSNParser => $dp); my $master_dbh = $sb->get_dbh_for('source'); -my $slave_dbh = $sb->get_dbh_for('replica1'); +my $replica_dbh = $sb->get_dbh_for('replica1'); my $master_dsn = { h => '127.1', P => '12345', @@ -45,7 +45,7 @@ my $ms = new MasterSlave( ); # ############################################################################ -# get_slaves() wrapper around recurse_to_slaves() +# get_replicas() wrapper around recurse_to_replicas() # ############################################################################ SKIP: { @@ -57,7 +57,7 @@ PXC_SKIP: { local @ARGV = (); $o->get_opts(); - my $slaves = $ms->get_slaves( + my $slaves = $ms->get_replicas( dbh => $master_dbh, dsn => $master_dsn, make_cxn => sub { @@ -87,14 +87,14 @@ PXC_SKIP: { source_id => 12345, source => 'hosts', }, - 'get_slaves() from recurse_to_slaves() with a default --recursion-method' + 'get_replicas() from recurse_to_replicas() with a default --recursion-method' ); my ($id) = $slaves->[0]->dbh()->selectrow_array('SELECT @@SERVER_ID'); is( $id, '12346', - 'dbh created from get_slaves()' + 'dbh created from get_replicas()' ); # This doesn't actually work because the master and slave are both @@ -105,7 +105,7 @@ PXC_SKIP: { local @ARGV = ('--recursion-method', 'processlist'); $o->get_opts(); - $slaves = $ms->get_slaves( + $slaves = $ms->get_replicas( dbh => $master_dbh, dsn => $master_dsn, make_cxn => sub { @@ -122,7 +122,7 @@ PXC_SKIP: { is_deeply( $slaves, [], - "get_slaves() by processlist" + "get_replicas() by processlist" ); # ########################################################################## @@ -151,7 +151,7 @@ PXC_SKIP: { $o->get_opts(); throws_ok( sub { - $slaves = $ms->get_slaves( + $slaves = $ms->get_replicas( dbh => $ro_dbh, dsn => $ro_dsn, make_cxn => sub { @@ -171,7 +171,7 @@ PXC_SKIP: { @ARGV = ('--recursion-method', 'none'); $o->get_opts(); - $slaves = $ms->get_slaves( + $slaves = $ms->get_replicas( dbh => $ro_dbh, dsn => $ro_dsn, make_cxn => sub { @@ -193,7 +193,7 @@ PXC_SKIP: { @ARGV = ('--recursion-method', 'none', '--recurse', '2'); $o->get_opts(); my $recursed = 0; - $ms->recurse_to_slaves( + $ms->recurse_to_replicas( { dbh => $ro_dbh, dsn => $ro_dsn, callback => sub { $recursed++ }, @@ -201,7 +201,7 @@ PXC_SKIP: { is( $recursed, 0, - "recurse_to_slaves() doesn't recurse if method=none" + "recurse_to_replicas() doesn't recurse if method=none" ); $ro_dbh->disconnect(); @@ -245,7 +245,7 @@ diag(`$trunk/sandbox/start-sandbox replica 2902 2901`); # | 2903 | 127.0.0.1 | 2903 | 0 | 2900 | # | 2901 | 127.0.0.1 | 2901 | 0 | 2900 | # +-----------+-----------+------+-------------------+-----------+ -# This caused recurse_to_slaves() to report 2903, 2901, 2902. +# This caused recurse_to_replicas() to report 2903, 2901, 2902. # Since the tests are senstive to the order of @slaves, they failed # because $slaves->[1] was no longer slave1 but slave0. Starting slave2 # last fixes/works around this. @@ -281,7 +281,7 @@ my $skip_callback = sub { @ARGV = ('--recurse', '2'); $o->get_opts(); -$ms->recurse_to_slaves( +$ms->recurse_to_replicas( { dbh => $dbh, dsn => $dsn, callback => $callback, @@ -315,9 +315,9 @@ is_deeply( # +- 127.0.0.1:slave0 # | +- 127.0.0.1:slave1 # +- 127.0.0.1:slave2 -is($ms->get_slave_status($slaves[0])->{source_port}, $port_for{source}, 'slave 1 port'); -is($ms->get_slave_status($slaves[1])->{source_port}, $port_for{replica0}, 'slave 2 port'); -is($ms->get_slave_status($slaves[2])->{source_port}, $port_for{source}, 'slave 3 port'); +is($ms->get_replica_status($slaves[0])->{source_port}, $port_for{source}, 'slave 1 port'); +is($ms->get_replica_status($slaves[1])->{source_port}, $port_for{replica0}, 'slave 2 port'); +is($ms->get_replica_status($slaves[2])->{source_port}, $port_for{source}, 'slave 3 port'); ok($ms->is_source_of($slaves[0], $slaves[1]), 'slave 1 is slave of slave 0'); eval { @@ -327,10 +327,10 @@ like($EVAL_ERROR, qr/but the ${source_name}'s port/, 'slave 2 is not slave of sl eval { $ms->is_source_of($slaves[2], $slaves[1]); }; -like($EVAL_ERROR, qr/has no connected slaves/, 'slave 1 is not slave of slave 2'); +like($EVAL_ERROR, qr/has no connected replicas/, 'slave 1 is not slave of slave 2'); -map { $ms->stop_slave($_) } @slaves; -map { $ms->start_slave($_) } @slaves; +map { $ms->stop_replica($_) } @slaves; +map { $ms->start_replica($_) } @slaves; # Give the slaves so time to restart sleep(5); @@ -338,13 +338,13 @@ sleep(5); my $res; $res = $ms->wait_for_source( source_status => $ms->get_source_status($dbh), - slave_dbh => $slaves[0], + replica_dbh => $slaves[0], timeout => 10, ); ok($res->{result} >= 0, 'Wait was successful'); -$ms->stop_slave($slaves[0]); +$ms->stop_replica($slaves[0]); $dbh->do('drop database if exists test'); $dbh->do('create database test'); $dbh->do('create table test.t(a int)'); @@ -354,18 +354,18 @@ diag(`(/tmp/$port_for{replica0}/use -e 'start ${replica_name}')&`); eval { $res = $ms->wait_for_source( source_status => $ms->get_source_status($dbh), - slave_dbh => $slaves[0], + replica_dbh => $slaves[0], timeout => 1, ); }; ok($res->{result}, 'Waited for some events'); # Clear any START SLAVE UNTIL conditions. -map { $ms->stop_slave($_) } @slaves; -map { $ms->start_slave($_) } @slaves; +map { $ms->stop_replica($_) } @slaves; +map { $ms->start_replica($_) } @slaves; sleep 1; -$ms->stop_slave($slaves[0]); +$ms->stop_replica($slaves[0]); $dbh->do('drop database if exists test'); # Any stmt will do eval { $res = $ms->catchup_to_source($slaves[0], $dbh, 10); @@ -373,7 +373,7 @@ eval { diag $EVAL_ERROR if $EVAL_ERROR; ok(!$EVAL_ERROR, 'No eval error catching up'); my $master_stat = $ms->get_source_status($dbh); -my $slave_stat = $ms->get_slave_status($slaves[0]); +my $slave_stat = $ms->get_replica_status($slaves[0]); is_deeply( $ms->repl_posn($master_stat), $ms->repl_posn($slave_stat), @@ -404,12 +404,12 @@ ok( ); ok( - !$ms->is_replication_thread($query, type=>'slave_io', check_known_ids=>0), + !$ms->is_replication_thread($query, type=>'replica_io', check_known_ids=>0), "Non-rpl thd is not slave io thd" ); ok( - !$ms->is_replication_thread($query, type=>'slave_sql', check_known_ids=>0), + !$ms->is_replication_thread($query, type=>'replica_sql', check_known_ids=>0), "Non-rpl thd is not slave sql thd" ); @@ -430,12 +430,12 @@ ok( ); ok( - !$ms->is_replication_thread($query, type=>'slave_io', check_known_ids=>0), + !$ms->is_replication_thread($query, type=>'replica_io', check_known_ids=>0), 'Binlog Dump is not a slave io thd' ); ok( - !$ms->is_replication_thread($query, type=>'slave_sql', check_known_ids=>0), + !$ms->is_replication_thread($query, type=>'replica_sql', check_known_ids=>0), 'Binlog Dump is not a slave sql thd' ); @@ -456,12 +456,12 @@ ok( ); ok( - $ms->is_replication_thread($query, type=>'slave_io', check_known_ids=>0), + $ms->is_replication_thread($query, type=>'replica_io', check_known_ids=>0), 'Slave io thd is a slave io thd' ); ok( - !$ms->is_replication_thread($query, type=>'slave_sql', check_known_ids=>0), + !$ms->is_replication_thread($query, type=>'replica_sql', check_known_ids=>0), 'Slave io thd is not a slave sql thd', ); @@ -482,12 +482,12 @@ ok( ); ok( - !$ms->is_replication_thread($query, type=>'slave_io', check_known_ids=>0), + !$ms->is_replication_thread($query, type=>'replica_io', check_known_ids=>0), 'Slave sql thd is not a slave io thd' ); ok( - $ms->is_replication_thread($query, type=>'slave_sql', check_known_ids=>0), + $ms->is_replication_thread($query, type=>'replica_sql', check_known_ids=>0), 'Slave sql thd is a slave sql thd', ); @@ -507,12 +507,12 @@ ok( 'Slave thread in init state matches all (issue 1121)', ); ok( - $ms->is_replication_thread($query, type=>'slave_io'), - 'Slave thread in init state matches slave_io (issue 1121)', + $ms->is_replication_thread($query, type=>'replica_io'), + 'Slave thread in init state matches replica_io (issue 1121)', ); ok( - $ms->is_replication_thread($query, type=>'slave_sql'), - 'Slave thread in init state matches slave_sql (issue 1121)', + $ms->is_replication_thread($query, type=>'replica_sql'), + 'Slave thread in init state matches replica_sql (issue 1121)', ); # Issue 1143: mk-kill Can Kill Slave's Replication Thread @@ -533,12 +533,12 @@ ok( 'Slave thread executing trigger matches all (issue 1143)', ); ok( - $ms->is_replication_thread($query, type=>'slave_io'), - 'Slave thread executing trigger matches slave_io (issue 1143)', + $ms->is_replication_thread($query, type=>'replica_io'), + 'Slave thread executing trigger matches replica_io (issue 1143)', ); ok( - $ms->is_replication_thread($query, type=>'slave_sql'), - 'Slave thread executing trigger matches slave_sql (issue 1143)', + $ms->is_replication_thread($query, type=>'replica_sql'), + 'Slave thread executing trigger matches replica_sql (issue 1143)', ); throws_ok( @@ -604,20 +604,20 @@ ok( # ############################################################################# SKIP: { skip "Cannot connect to sandbox master", 3 unless $master_dbh; - skip "Cannot connect to sandbox slave", 3 unless $slave_dbh; + skip "Cannot connect to sandbox slave", 3 unless $replica_dbh; PXC_SKIP: { skip 'Not for PXC' if ( $sb->is_cluster_mode ); is_deeply( - $ms->get_replication_filters(dbh=>$slave_dbh), + $ms->get_replication_filters(dbh=>$replica_dbh), { }, "No replication filters" ); $master_dbh->disconnect(); - $slave_dbh->disconnect(); + $replica_dbh->disconnect(); diag(`/tmp/12346/stop >/dev/null 2>&1`); diag(`/tmp/12345/stop >/dev/null 2>&1`); @@ -629,7 +629,7 @@ PXC_SKIP: { diag(`/tmp/12346/start >/dev/null 2>&1`); $master_dbh = $sb->get_dbh_for('source'); - $slave_dbh = $sb->get_dbh_for('replica1'); + $replica_dbh = $sb->get_dbh_for('replica1'); is_deeply( $ms->get_replication_filters(dbh=>$master_dbh), @@ -640,7 +640,7 @@ PXC_SKIP: { ); is_deeply( - $ms->get_replication_filters(dbh=>$slave_dbh), + $ms->get_replication_filters(dbh=>$replica_dbh), { replicate_ignore_db => 'foo', }, @@ -656,29 +656,29 @@ PXC_SKIP: { diag(`/tmp/12347/use -e "STOP ${replica_name}; START ${replica_name};" >/dev/null`); $master_dbh = $sb->get_dbh_for('source'); - $slave_dbh = $sb->get_dbh_for('replica1'); + $replica_dbh = $sb->get_dbh_for('replica1'); }; is( - $ms->get_slave_lag($dbh), + $ms->get_replica_lag($dbh), undef, - "get_slave_lag() for master" + "get_replica_lag() for master" ); ok( - defined $ms->get_slave_lag($slaves[1]), - "get_slave_lag() for slave" + defined $ms->get_replica_lag($slaves[1]), + "get_replica_lag() for slave" ); # ############################################################################ -# get_slaves() and DSN table +# get_replicas() and DSN table # ############################################################################ $sb->load_file('source', "t/lib/samples/MasterSlave/dsn_table.sql"); @ARGV = ('--recursion-method', 'dsn=F=/tmp/12345/my.sandbox.cnf,D=dsn_t,t=dsns'); $o->get_opts(); -my $slaves = $ms->get_slaves( +my $slaves = $ms->get_replicas( OptionParser => $o, DSNParser => $dp, Quoter => $q, @@ -706,7 +706,7 @@ is_deeply( u => 'msandbox', mysql_ssl => undef, }, - 'get_slaves() from DSN table' + 'get_replicas() from DSN table' ); my ($id) = $slaves->[0]->dbh()->selectrow_array('SELECT @@SERVER_ID'); @@ -788,7 +788,7 @@ SKIP: { my $chan_slaves; eval { - $chan_slaves = $ms->get_slaves( + $chan_slaves = $ms->get_replicas( dbh => $master1_dbh, dsn => $master1_dsn, make_cxn => sub { @@ -808,7 +808,7 @@ SKIP: { #}; my $css; eval { - $css = $ms->get_slave_status($slave1_dbh); + $css = $ms->get_replica_status($slave1_dbh); }; #local $SIG{__WARN__} = undef; is ( @@ -819,15 +819,15 @@ SKIP: { like ( $EVAL_ERROR, - qr/This server returned more than one row for SHOW SLAVE STATUS/, - 'Got warning message if we cannot determine slave in a multi source config without --channel param', + qr/This server returned more than one row for SHOW (REPLICA|SLAVE) STATUS/, + 'Got warning message if we cannot determine replica in a multi source config without --channel param', ); my $wfm; eval { $wfm = $ms->wait_for_source( source_status => $ms->get_source_status($dbh), - slave_dbh => $slave1_dbh, + replica_dbh => $slave1_dbh, timeout => 1, ); }; @@ -845,7 +845,7 @@ SKIP: { $slave1_dbh->do("STOP ${replica_name} for channel 'sourcechan2'"); eval { - $css = $ms->get_slave_status($slave1_dbh); + $css = $ms->get_replica_status($slave1_dbh); }; is ( $css, @@ -857,7 +857,7 @@ SKIP: { # Now try specifying a channel name $ms->{channel} = 'sourcechan1'; - $css = $ms->get_slave_status($slave1_dbh); + $css = $ms->get_replica_status($slave1_dbh); is ( $css->{channel_name}, 'sourcechan1', @@ -866,7 +866,7 @@ SKIP: { $wfm = $ms->wait_for_source( source_status => $ms->get_source_status($dbh), - slave_dbh => $slave1_dbh, + replica_dbh => $slave1_dbh, timeout => 1, ); is( @@ -893,7 +893,7 @@ my $connected_slaves = [ }, ]; -my @g = $ms->_process_slaves_list ($dp, $dsn, $connected_slaves); +my @g = $ms->_process_replicas_list ($dp, $dsn, $connected_slaves); is ( scalar @g, 1, diff --git a/t/lib/ReplicaLagWaiter.t b/t/lib/ReplicaLagWaiter.t index d74c34d1..2dae6229 100644 --- a/t/lib/ReplicaLagWaiter.t +++ b/t/lib/ReplicaLagWaiter.t @@ -11,8 +11,7 @@ use warnings FATAL => 'all'; use English qw(-no_match_vars); use Test::More; -plan skip_all => 'FIXME ReplicaLagWaiter.t'; -#plan tests => 7; +plan tests => 7; use ReplicaLagWaiter; use OptionParser; @@ -68,7 +67,7 @@ my $rll = new ReplicaLagWaiter( get_lag => \&get_lag, sleep => \&sleep, max_lag => 1, - slaves => [$r1, $r2], + replicas => [$r1, $r2], ); @lag = (0, 0); diff --git a/t/lib/Safeguards.t b/t/lib/Safeguards.t deleted file mode 100644 index 43d6db5c..00000000 --- a/t/lib/Safeguards.t +++ /dev/null @@ -1,69 +0,0 @@ -#!/usr/bin/perl - -BEGIN { - die "The PERCONA_TOOLKIT_BRANCH environment variable is not set.\n" - unless $ENV{PERCONA_TOOLKIT_BRANCH} && -d $ENV{PERCONA_TOOLKIT_BRANCH}; - unshift @INC, "$ENV{PERCONA_TOOLKIT_BRANCH}/lib"; -}; - -use strict; -use warnings FATAL => 'all'; -use English qw(-no_match_vars); -use Test::More; - -use Safeguards; -use Percona::Test; - -use Data::Dumper; -$Data::Dumper::Indent = 1; -$Data::Dumper::Sortkeys = 1; -$Data::Dumper::Quotekeys = 0; - -my $sample = "t/lib/samples/bash/"; - -my $safeguards = Safeguards->new( - disk_bytes_free => 104857600, - disk_pct_free => 10, -); - -# Filesystem 1024-blocks Used Available Capacity Mounted on -# /dev/disk0s2 118153176 94409664 23487512 81% / -# -# Those values are in Kb, so: -# used = 94409664 (94.4G) = 96_675_495_936 bytes -# free = 23487512 (23.4G) = 24_051_212_288 bytes -# pct free = 100 - 81 = 19 % -my $df = slurp_file("$trunk/$sample/diskspace001.txt"); - -ok( - $safeguards->check_disk_space( - disk_space => $df, - ), - "diskspace001: Enough bytes and pct free" -); - -$safeguards = Safeguards->new( - disk_bytes_free => 104857600, - disk_pct_free => 20, -); - -ok( - !$safeguards->check_disk_space( - disk_space => $df, - ), - "diskspace001: Not enough pct free" -); - -$safeguards = Safeguards->new( - disk_bytes_free => 24_051_212_289, - disk_pct_free => 5, -); - -ok( - !$safeguards->check_disk_space( - disk_space => $df, - ), - "diskspace001: Not enough bytes free" -); - -done_testing; diff --git a/t/lib/TableSyncer.t b/t/lib/TableSyncer.t index 8a7c44cc..0945737d 100644 --- a/t/lib/TableSyncer.t +++ b/t/lib/TableSyncer.t @@ -1004,7 +1004,7 @@ my $output = ''; }, ); }, - qr/Slave did not catch up to its source after 2 attempts of waiting 60/, + qr/Replica did not catch up to its source after 2 attempts of waiting 60/, "Retries wait" ); } diff --git a/t/lib/bash/report_mysql_info.sh b/t/lib/bash/report_mysql_info.sh index 08e13ed5..24d0e78a 100644 --- a/t/lib/bash/report_mysql_info.sh +++ b/t/lib/bash/report_mysql_info.sh @@ -147,7 +147,7 @@ master wait_pos_backtraverse | master yes_tx | EOF -_semi_sync_stats_for "master" "$samples/mysql-variables-with-semisync.txt" > "$PT_TMPDIR/got" +_semi_sync_stats_for "master" "$samples/mysql-variables-with-semisync.txt" "slave" > "$PT_TMPDIR/got" no_diff "$PT_TMPDIR/expected" "$PT_TMPDIR/got" "semisync replication" # ########################################################################### @@ -805,20 +805,20 @@ is \ # https://bugs.launchpad.net/percona-toolkit/+bug/1015590 # ########################################################################### -section_percona_server_features "$samples/percona-server-5.5-variables" > "$PT_TMPDIR/got" +section_percona_server_features "$samples/percona-server-5.5-variables" "slave" > "$PT_TMPDIR/got" no_diff \ "$PT_TMPDIR/got" \ "$samples/expected_output_ps-features.txt" \ "Bug 1015590: pt-mysql-summary not Percona Server 5.5-ready" -section_percona_server_features "$samples/percona-server-5.1-variables" > "$PT_TMPDIR/got" +section_percona_server_features "$samples/percona-server-5.1-variables" "slave" > "$PT_TMPDIR/got" no_diff \ "$PT_TMPDIR/got" \ "$samples/expected_output_ps-5.1-features.txt" \ "Bug 1015590: section_percona_server_features works on 5.1 with innodb_adaptive_checkpoint=none" -section_percona_server_features "$samples/percona-server-5.1-variables-martin" > "$PT_TMPDIR/got" +section_percona_server_features "$samples/percona-server-5.1-variables-martin" "slave" > "$PT_TMPDIR/got" no_diff \ "$PT_TMPDIR/got" \ "$samples/expected_output_ps-5.1-martin.txt" \