diff --git a/bin/pt-archiver b/bin/pt-archiver index 43d7265d..91d9a82b 100755 --- a/bin/pt-archiver +++ b/bin/pt-archiver @@ -6275,6 +6275,7 @@ sub main { OptionParser => $o, DSNParser => $dp, Quoter => $q, + channel => $o->get('channel'), ); # we get each slave's connection handler (and its id, for debug and reporting) for my $slave (@$lag_slaves_dsn) { @@ -7472,6 +7473,18 @@ If C throws an error in the lines of C, refer to the documentation for the C DSN option. +=item --channel + +type: string + +Channel name used when connected to a server using replication channels. +Suppose you have two masters, master_a at port 12345, master_b at port 1236 and +a slave connected to both masters using channels chan_master_a and chan_master_b. +If you want to run pt-archiver to syncronize the slave against master_a, pt-archiver +won't be able to determine what's the correct master since SHOW SLAVE STATUS +will return 2 rows. In this case, you can use --channel=chan_master_a to specify +the channel name to use in the SHOW SLAVE STATUS command. + =item --charset short form: -A; type: string diff --git a/t/pt-archiver/archive_using_channels.t b/t/pt-archiver/archive_using_channels.t new file mode 100644 index 00000000..0e4fe6f5 --- /dev/null +++ b/t/pt-archiver/archive_using_channels.t @@ -0,0 +1,113 @@ +#!/usr/bin/env 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 PerconaTest; +use Sandbox; +require "$trunk/bin/pt-archiver"; + +my $dp = new DSNParser(opts=>$dsn_opts); +my $sb = new Sandbox(basedir => '/tmp', DSNParser => $dp); +my $master_dbh = $sb->get_dbh_for('master'); +my $slave_dbh = $sb->get_dbh_for('slave1'); + +if ( !$master_dbh ) { + plan skip_all => 'Cannot connect to sandbox master'; +} +elsif ( !$slave_dbh ) { + plan skip_all => 'Cannot connect to sandbox slave'; +} elsif ($sandbox_version lt '5.7') { + plan skip_all => 'Only on MySQL 5.7+'; +} else { + plan tests => 5; +} + +my ($master1_dbh, $master1_dsn) = $sb->start_sandbox( + server => 'chan_master1', + type => 'master', +); +my ($master2_dbh, $master2_dsn) = $sb->start_sandbox( + server => 'chan_master2', + type => 'master', +); +my ($slave1_dbh, $slave1_dsn) = $sb->start_sandbox( + server => 'chan_slave1', + type => 'master', +); +my $slave1_port = $sb->port_for('chan_slave1'); + +$sb->load_file('chan_master1', "sandbox/gtid_on.sql", undef, no_wait => 1); +$sb->load_file('chan_master2', "sandbox/gtid_on.sql", undef, no_wait => 1); +$sb->load_file('chan_slave1', "sandbox/slave_channels.sql", undef, no_wait => 1); + +my $master1_port = $sb->port_for('chan_master1'); +my $num_rows = 40000; + +# Load some rows into masters 1 & 2. +$sb->load_file('chan_master1', "t/pt-archiver/samples/channels.sql", undef, no_wait => 1); + +diag("Loading $num_rows into the test.t1 table on first master. This might take some time."); +diag(`util/mysql_random_data_load --host=127.0.0.1 --port=$master1_port --user=msandbox --password=msandbox test t1 $num_rows`); +diag("$num_rows rows loaded. Starting tests."); +$master_dbh->do("FLUSH TABLES"); + +my $rows = $master1_dbh->selectrow_arrayref('SELECT COUNT(*) FROM test.t1 '); + +is( + @$rows[0], + $num_rows, + "All rows were loaded into master 1", +); + +my @args = ('--source', $master1_dsn.',D=test,t=t1', '--purge', '--where', sprintf('id >= %d', $num_rows / 2), '--check-slave-lag', $slave1_dsn); + +my ($exit_status, $output); + +$output = output( + sub { $exit_status = pt_archiver::main(@args) }, + stderr => 1, +); + +isnt( + $exit_status, + 0, + 'Must specify a channel name', +); + +like ( + $output, + qr/"channel" was not specified/, + 'Message saying channel name must be specified' +); + +push @args, ('--channel', 'masterchan1'); + +output( + sub { $exit_status = pt_archiver::main(@args, '--channel', 'masterchan1') }, + stderr => 1, +); + +is( + $exit_status, + 0, + 'Ok if channel name was specified', +); + +$sb->stop_sandbox(qw(chan_master1 chan_master2 chan_slave1)); + + +# ############################################################################# +# Done. +# ############################################################################# +$sb->wipe_clean($master_dbh); +ok($sb->ok(), "Sandbox servers") or BAIL_OUT(__FILE__ . " broke the sandbox"); +exit; diff --git a/t/pt-archiver/samples/channels.sql b/t/pt-archiver/samples/channels.sql new file mode 100644 index 00000000..42260345 --- /dev/null +++ b/t/pt-archiver/samples/channels.sql @@ -0,0 +1,6 @@ +DROP DATABASE IF EXISTS test; +CREATE DATABASE test; +CREATE TABLE test.t1 ( + id INT PRIMARY KEY AUTO_INCREMENT, + f2 VARCHAR(25) +) Engine=InnoDB;