Change --skip-gtid-uuid to --master-uuid. Make test more reliable. Simplify code and clean up docs.

This commit is contained in:
Daniel Nichter
2014-05-28 13:31:10 -07:00
parent b3c6a0aac2
commit 3b96187313
5 changed files with 174 additions and 143 deletions

View File

@@ -4982,8 +4982,8 @@ sub watch_server {
$start_sql .= " UNTIL RELAY_LOG_FILE = '$file', RELAY_LOG_POS = $pos";
}
my $start = $dbh->prepare($start_sql);
my $stop = $dbh->prepare('STOP SLAVE');
my $start = $dbh->prepare($start_sql);
my $stop = $dbh->prepare('STOP SLAVE');
# ########################################################################
# Detect if GTID is enabled. Skipping an event is done differently.
@@ -4991,27 +4991,25 @@ sub watch_server {
# When MySQL 5.6.5 or higher is used and gtid is enabled, skipping a
# transaction is not possible with SQL_SLAVE_SKIP_COUNTER
my $skip_event;
my $gtid_mode;
my $have_gtid = 0;
if ( VersionParser->new($dbh) >= '5.6.5' ) {
my $row = $dbh->selectrow_arrayref('SELECT @@GLOBAL.gtid_mode');
$gtid_mode = $row->[0];
} else {
$gtid_mode="N/A";
my $row = $dbh->selectrow_arrayref('SELECT @@GLOBAL.gtid_mode');
PTDEBUG && _d('@@GLOBAL.gtid_mode:', $row->[0]);
if ( $row && $row->[0] eq 'ON' ) {
$have_gtid = 1;
}
}
PTDEBUG && _d('GTID is ' . ($gtid_mode eq 'ON'
? 'enabled'
: 'disabled'));
PTDEBUG && _d('Have GTID:', $have_gtid);
# If GTID is enabled, slave_parallel_workers should be == 0.
# it's currently not possible to know what GTID event the failed trx is
if ( $gtid_mode eq 'ON') {
my $threads = $dbh->selectrow_hashref('SELECT
@@GLOBAL.slave_parallel_workers AS threads');
# It's currently not possible to know what GTID event the failed trx is.
if ( $have_gtid ) {
my $threads = $dbh->selectrow_hashref(
'SELECT @@GLOBAL.slave_parallel_workers AS threads');
if ( $threads->{threads} > 0 ) {
die("Error: GTID is enabled, and slave_parallel_workers="
. $threads->{threads}
. ". It is impossible to skip transactions properly.\n");
die "Cannot skip transactions properly because GTID is enabled "
. "and slave_parallel_workers > 0. See 'GLOBAL TRANSACTION IDS' "
. "in the tool's documentation.\n";
}
}
@@ -5023,9 +5021,7 @@ sub watch_server {
[ qr/Could not parse relay log event entry/ => 'refetch_relay_log' ],
[ qr/Incorrect key file for table/ => 'repair_table' ],
# This must be the last one. It's a catch-all rule: skip and restart.
[ qr/./ => ($gtid_mode eq 'ON'
? 'skip_gtid'
: 'skip') ],
[ qr/./ => ($have_gtid ? 'skip_gtid' : 'skip') ],
);
# ########################################################################
@@ -5054,6 +5050,14 @@ sub watch_server {
},
skip_gtid => sub {
my ( $stat, $dbh ) = @_;
# Get master_uuid from SHOW SLAVE STATUS if a UUID is not specified
# with --master-uuid.
my $gtid_uuid = $o->get('master-uuid');
if ( !$gtid_uuid ) {
$gtid_uuid = $stat->{master_uuid};
die "No master_uuid" unless $gtid_uuid; # shouldn't happen
}
# We need the highest transaction in the executed_gtid_set.
# and then we need to increase it by 1 (the one we want to skip)
@@ -5062,54 +5066,38 @@ sub watch_server {
# - it skips the next transaction from the master_uuid
# (when a slaveB is replicating from slaveA,
# the master_uuid is it's own master, slaveA)
my $gtid_exec = $stat->{executed_gtid_set};
# default behavior is to take the master_uuid from SHOW SLAVE STATUS
# or use --skip-gtid-uuid specified uuid.
my $gtid_uuid;
if ( $o->get('skip-gtid-uuid') eq 'master' ) {
$gtid_uuid = $stat->{master_uuid};
} else {
$gtid_uuid = $o->get('skip-gtid-uuid');
}
$gtid_exec =~ /$gtid_uuid([0-9-:]*)/;
my $gtid_exec_ids = $1;
$gtid_exec_ids =~ s/:[0-9]-/:/g;
my ($gtid_exec_ids) = ($stat->{executed_gtid_set} || '') =~ m/$gtid_uuid([0-9-:]*)/;
$gtid_exec_ids =~ s/:[0-9]-/:/g;
die "No executed GTIDs" unless $gtid_exec_ids;
my @gtid_exec_ranges = split(/:/, $gtid_exec_ids);
delete $gtid_exec_ranges[0]; # undef the first value,it's always empty
delete $gtid_exec_ranges[0]; # undef the first value, it's always empty
# get the highest id by sorting the array, removing the undef value
# Get the highest id by sorting the array, removing the undef value.
my @gtid_exec_sorted = sort { $a <=> $b }
grep { defined($_) } @gtid_exec_ranges;
my $gtid_exec_last = $gtid_exec_sorted[-1];
PTDEBUG && _d("GTID: master_uuid:$gtid_uuid,\n"
. "GTID: executed_gtid_set:$gtid_exec,\n"
. "GTID: gtid max for master_uuid:" . $gtid_exec_sorted[-1] . "\n"
. "GTID: last executed gtid:'$gtid_uuid:$gtid_exec_last'");
PTDEBUG && _d("\n",
"GTID: master_uuid:", $gtid_uuid, "\n",
"GTID: executed_gtid_set:", $gtid_exec_ids, "\n",
"GTID: max for master_uuid:", $gtid_exec_sorted[-1], "\n",
"GTID: last executed gtid:", $gtid_uuid, ":", $gtid_exec_last);
# Set the sessions next gtid, write an empty transaction
my $skipped=0;
until ( $skipped == $o->get('skip-count') ) {
$skipped++;
my $gtid_next=$gtid_exec_last + $skipped;
PTDEBUG && _d("GTID: Skipping " . $gtid_uuid . ":" . $gtid_next);
my $gtid_set_next = $dbh->prepare("SET GTID_NEXT='"
. $gtid_uuid . ":" . $gtid_next . "'");
$gtid_set_next->execute();
my $skipped = 0;
while ( $skipped++ < $o->get('skip-count') ) {
my $gtid_next = $gtid_exec_last + $skipped;
my $sql = "SET GTID_NEXT='$gtid_uuid:$gtid_next'";
PTDEBUG && _d($sql);
my $sth = $dbh->prepare($sql);
$sth->execute();
$dbh->begin_work();
$dbh->commit();
}
# Set the session back to the automatically generated GTID_NEXT.
my $gtid_automatic = $dbh->prepare("SET GTID_NEXT='AUTOMATIC'");
$gtid_automatic->execute();
$dbh->do("SET GTID_NEXT='AUTOMATIC'");
},
repair_table => sub {
my ( $stat, $dbh ) = @_;
@@ -5399,25 +5387,23 @@ sleep time, whichever is less.
=head1 GLOBAL TRANSACTION IDS
pt-slave-restart supports Global Transaction IDs, which has been introduced in
MySQL in 5.6.5.
It's important to keep in mind that:
As of Percona Toolkit 2.2.8, pt-slave-restart supports Global Transaction IDs
introduced in MySQL 5.6.5. It's important to keep in mind that:
=over
=item *
pt-slave-restart will not skip transactions when multiple replication threads
are being used (slave_parallel_workers>0). pt-slave-restart does not know what
the GTID event is of the failed transaction of a specific slave thread.
are being used (slave_parallel_workers > 0). pt-slave-restart does not know
what the GTID event is of the failed transaction of a specific slave thread.
=item *
The default behavior is to skip the next transaction from the slave's master.
Writes can originate on different servers, each with their own unique UUID.
Writes can originate on different servers, each with their own UUID.
See L<"--skip-gtid-uuid">.
See L<"--master-uuid">.
=back
@@ -5675,20 +5661,23 @@ type: int; default: 1
Number of statements to skip when restarting the slave.
=item --skip-gtid-uuid
=item --master-uuid
type: string; default: master
type: string
When using GTID, an empty transaction should be created in order to skip it.
If writes are coming from different nodes in the replication tree above, it is
not possible to know which event from which UUID to skip.
By default, the UUID from the slave's master is being used to skip.
(C<SHOW GLOBAL STATUS Master_UUID> column).
By default, transactions from the slave's master (C<'Master_UUID'> from
C<SHOW SLAVE STATUS>) are skipped.
Example: Master -> Slave1 -> Slave2. When skipping events from 'Slave2', and
writes originated from 'Master', --skip-gtid-uuid should be specified with the
'Master' it's UUID.
For example, with
master1 -> slave1 -> slave2
When skipping events on slave2 that were written to master1, you must specify
the UUID of master1, else the tool will use the UUID of slave1 by default.
See L<"GLOBAL TRANSACTION IDS">.