mirror of
https://github.com/percona/percona-toolkit.git
synced 2025-09-02 02:34:19 +00:00
PT-2340 - Support MySQL 8.4
- Added deprecation warning to pt-slave-delay - Re-enabled tests for pt-slave-delay to check the warning - Disabled pt-slave-delay for MySQL 8.1+
This commit is contained in:
@@ -26,6 +26,7 @@ BEGIN {
|
||||
Retry
|
||||
HTTP::Micro
|
||||
VersionCheck
|
||||
VersionParser
|
||||
));
|
||||
}
|
||||
|
||||
@@ -4293,6 +4294,198 @@ sub _d {
|
||||
# End VersionCheck package
|
||||
# ###########################################################################
|
||||
|
||||
# ###########################################################################
|
||||
# VersionParser package
|
||||
# This package is a copy without comments from the original. The original
|
||||
# with comments and its test file can be found in the GitHub repository at,
|
||||
# lib/VersionParser.pm
|
||||
# t/lib/VersionParser.t
|
||||
# See https://github.com/percona/percona-toolkit for more information.
|
||||
# ###########################################################################
|
||||
{
|
||||
package VersionParser;
|
||||
|
||||
use Lmo;
|
||||
use Scalar::Util qw(blessed);
|
||||
use English qw(-no_match_vars);
|
||||
use constant PTDEBUG => $ENV{PTDEBUG} || 0;
|
||||
|
||||
use overload (
|
||||
'""' => "version",
|
||||
'<=>' => "cmp",
|
||||
'cmp' => "cmp",
|
||||
fallback => 1,
|
||||
);
|
||||
|
||||
use Carp ();
|
||||
|
||||
has major => (
|
||||
is => 'ro',
|
||||
isa => 'Int',
|
||||
required => 1,
|
||||
);
|
||||
|
||||
has [qw( minor revision )] => (
|
||||
is => 'ro',
|
||||
isa => 'Num',
|
||||
);
|
||||
|
||||
has flavor => (
|
||||
is => 'ro',
|
||||
isa => 'Str',
|
||||
default => sub { 'Unknown' },
|
||||
);
|
||||
|
||||
has innodb_version => (
|
||||
is => 'ro',
|
||||
isa => 'Str',
|
||||
default => sub { 'NO' },
|
||||
);
|
||||
|
||||
sub series {
|
||||
my $self = shift;
|
||||
return $self->_join_version($self->major, $self->minor);
|
||||
}
|
||||
|
||||
sub version {
|
||||
my $self = shift;
|
||||
return $self->_join_version($self->major, $self->minor, $self->revision);
|
||||
}
|
||||
|
||||
sub is_in {
|
||||
my ($self, $target) = @_;
|
||||
|
||||
return $self eq $target;
|
||||
}
|
||||
|
||||
sub _join_version {
|
||||
my ($self, @parts) = @_;
|
||||
|
||||
return join ".", map { my $c = $_; $c =~ s/^0\./0/; $c } grep defined, @parts;
|
||||
}
|
||||
sub _split_version {
|
||||
my ($self, $str) = @_;
|
||||
my @version_parts = map { s/^0(?=\d)/0./; $_ } $str =~ m/(\d+)/g;
|
||||
return @version_parts[0..2];
|
||||
}
|
||||
|
||||
sub normalized_version {
|
||||
my ( $self ) = @_;
|
||||
my $result = sprintf('%d%02d%02d', map { $_ || 0 } $self->major,
|
||||
$self->minor,
|
||||
$self->revision);
|
||||
PTDEBUG && _d($self->version, 'normalizes to', $result);
|
||||
return $result;
|
||||
}
|
||||
|
||||
sub comment {
|
||||
my ( $self, $cmd ) = @_;
|
||||
my $v = $self->normalized_version();
|
||||
|
||||
return "/*!$v $cmd */"
|
||||
}
|
||||
|
||||
my @methods = qw(major minor revision);
|
||||
sub cmp {
|
||||
my ($left, $right) = @_;
|
||||
my $right_obj = (blessed($right) && $right->isa(ref($left)))
|
||||
? $right
|
||||
: ref($left)->new($right);
|
||||
|
||||
my $retval = 0;
|
||||
for my $m ( @methods ) {
|
||||
last unless defined($left->$m) && defined($right_obj->$m);
|
||||
$retval = $left->$m <=> $right_obj->$m;
|
||||
last if $retval;
|
||||
}
|
||||
return $retval;
|
||||
}
|
||||
|
||||
sub BUILDARGS {
|
||||
my $self = shift;
|
||||
|
||||
if ( @_ == 1 ) {
|
||||
my %args;
|
||||
if ( blessed($_[0]) && $_[0]->can("selectrow_hashref") ) {
|
||||
PTDEBUG && _d("VersionParser got a dbh, trying to get the version");
|
||||
my $dbh = $_[0];
|
||||
local $dbh->{FetchHashKeyName} = 'NAME_lc';
|
||||
my $query = eval {
|
||||
$dbh->selectall_arrayref(q/SHOW VARIABLES LIKE 'version%'/, { Slice => {} })
|
||||
};
|
||||
if ( $query ) {
|
||||
$query = { map { $_->{variable_name} => $_->{value} } @$query };
|
||||
@args{@methods} = $self->_split_version($query->{version});
|
||||
$args{flavor} = delete $query->{version_comment}
|
||||
if $query->{version_comment};
|
||||
}
|
||||
elsif ( eval { ($query) = $dbh->selectrow_array(q/SELECT VERSION()/) } ) {
|
||||
@args{@methods} = $self->_split_version($query);
|
||||
}
|
||||
else {
|
||||
Carp::confess("Couldn't get the version from the dbh while "
|
||||
. "creating a VersionParser object: $@");
|
||||
}
|
||||
$args{innodb_version} = eval { $self->_innodb_version($dbh) };
|
||||
}
|
||||
elsif ( !ref($_[0]) ) {
|
||||
@args{@methods} = $self->_split_version($_[0]);
|
||||
}
|
||||
|
||||
for my $method (@methods) {
|
||||
delete $args{$method} unless defined $args{$method};
|
||||
}
|
||||
@_ = %args if %args;
|
||||
}
|
||||
|
||||
return $self->SUPER::BUILDARGS(@_);
|
||||
}
|
||||
|
||||
sub _innodb_version {
|
||||
my ( $self, $dbh ) = @_;
|
||||
return unless $dbh;
|
||||
my $innodb_version = "NO";
|
||||
|
||||
my ($innodb) =
|
||||
grep { $_->{engine} =~ m/InnoDB/i }
|
||||
map {
|
||||
my %hash;
|
||||
@hash{ map { lc $_ } keys %$_ } = values %$_;
|
||||
\%hash;
|
||||
}
|
||||
@{ $dbh->selectall_arrayref("SHOW ENGINES", {Slice=>{}}) };
|
||||
if ( $innodb ) {
|
||||
PTDEBUG && _d("InnoDB support:", $innodb->{support});
|
||||
if ( $innodb->{support} =~ m/YES|DEFAULT/i ) {
|
||||
my $vars = $dbh->selectrow_hashref(
|
||||
"SHOW VARIABLES LIKE 'innodb_version'");
|
||||
$innodb_version = !$vars ? "BUILTIN"
|
||||
: ($vars->{Value} || $vars->{value});
|
||||
}
|
||||
else {
|
||||
$innodb_version = $innodb->{support}; # probably DISABLED or NO
|
||||
}
|
||||
}
|
||||
|
||||
PTDEBUG && _d("InnoDB version:", $innodb_version);
|
||||
return $innodb_version;
|
||||
}
|
||||
|
||||
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";
|
||||
}
|
||||
|
||||
no Lmo;
|
||||
1;
|
||||
}
|
||||
# ###########################################################################
|
||||
# End VersionParser package
|
||||
# ###########################################################################
|
||||
|
||||
# ###########################################################################
|
||||
# This is a combination of modules and programs in one -- a runnable module.
|
||||
# http://www.perl.com/pub/a/2006/07/13/lightning-articles.html?page=last
|
||||
@@ -4319,6 +4512,8 @@ my $oktorun = 1;
|
||||
sub main {
|
||||
local @ARGV = @_; # set global ARGV for this package
|
||||
|
||||
warn "This tool is deprecated and will be removed in future releases.\nUse built-in Delayed Replication instead: https://dev.mysql.com/doc/refman/8.4/en/replication-delayed.html\n\n";
|
||||
|
||||
$o = new OptionParser();
|
||||
$o->get_specs();
|
||||
$o->get_opts();
|
||||
@@ -4355,6 +4550,13 @@ sub main {
|
||||
|
||||
# Connect before daemonizing, in case --ask-pass is needed.
|
||||
my $slave_dbh = get_dbh($dp, $slave_dsn);
|
||||
|
||||
# Check version, refuse working with 8.4
|
||||
my $version = VersionParser->new($slave_dbh);
|
||||
if ( $version ge '8.1' && $version->flavor() !~ m/maria/ ) {
|
||||
die "This tool does not work with MySQL 8.1 and newer.\n";
|
||||
}
|
||||
|
||||
my $status = $slave_dbh->selectrow_hashref("SHOW SLAVE STATUS");
|
||||
if ( !$status || ! %$status ) {
|
||||
die "No SLAVE STATUS found";
|
||||
@@ -4654,6 +4856,10 @@ if ( !caller ) { exit main(@ARGV); }
|
||||
|
||||
pt-slave-delay - Make a MySQL slave server lag behind its master.
|
||||
|
||||
This tool is deprecated and will be removed in future releases. It does not support MySQL 8.1 or newer.
|
||||
|
||||
Use built-in Delayed Replication instead: https://dev.mysql.com/doc/refman/8.4/en/replication-delayed.html
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
Usage: pt-slave-delay [OPTIONS] SLAVE_DSN [MASTER_DSN]
|
||||
|
@@ -88,7 +88,7 @@ our $source_status = 'binary log';
|
||||
our $source_reset = 'binary logs and gtids';
|
||||
our $source_change = 'replication source';
|
||||
our $replica_name = 'replica';
|
||||
if ( $sandbox_version < '8.1' || ( $ENV{FORK} || "" eq 'mariadb' ) ) {
|
||||
if ( $sandbox_version lt '8.1' || ( $ENV{FORK} || "" eq 'mariadb' ) ) {
|
||||
$source_name = 'master';
|
||||
$source_status = 'master';
|
||||
$source_reset = 'master';
|
||||
|
@@ -22,8 +22,8 @@ my $sb = Sandbox->new(basedir => '/tmp', DSNParser => $dp);
|
||||
my $source_dbh = $sb->get_dbh_for('source');
|
||||
my $dbh = $sb->get_dbh_for('replica1');
|
||||
|
||||
if ($sandbox_version ge '5.7') {
|
||||
plan skip_all => 'Use SQL_DELAY';
|
||||
if ($sandbox_version ge '8.1') {
|
||||
plan skip_all => 'Tool is not supported. Use SQL_DELAY';
|
||||
}
|
||||
|
||||
if ( !$dbh ) {
|
||||
@@ -72,7 +72,7 @@ else {
|
||||
# Reap the child.
|
||||
waitpid ($pid, 0);
|
||||
|
||||
$sb->wait_for_slaves;
|
||||
$sb->wait_for_replicas;
|
||||
|
||||
# Do it all over again, but this time KILL instead of restart.
|
||||
$pid = fork();
|
||||
@@ -92,7 +92,7 @@ if ( $pid ) {
|
||||
else {
|
||||
# child. Note that we'll kill the parent's 'mysql' connection
|
||||
sleep 1;
|
||||
my $c_dbh = $sb->get_dbh_for('slave1');
|
||||
my $c_dbh = $sb->get_dbh_for('replica1');
|
||||
my @cxn = @{$c_dbh->selectall_arrayref('show processlist', {Slice => {}})};
|
||||
foreach my $c ( @cxn ) {
|
||||
# The parent's connection:
|
||||
|
@@ -21,8 +21,8 @@ my $master_dbh = $sb->get_dbh_for('source');
|
||||
my $slave1_dbh = $sb->get_dbh_for('replica1');
|
||||
my $slave2_dbh = $sb->get_dbh_for('replica2');
|
||||
|
||||
if ($sandbox_version ge '5.7') {
|
||||
plan skip_all => 'Use SQL_DELAY';
|
||||
if ($sandbox_version ge '8.1') {
|
||||
plan skip_all => 'Tool is not supported. Use SQL_DELAY';
|
||||
}
|
||||
|
||||
if ( !$master_dbh ) {
|
||||
@@ -35,7 +35,7 @@ elsif ( !$slave2_dbh ) {
|
||||
plan skip_all => 'Cannot connect to sandbox slave2';
|
||||
}
|
||||
else {
|
||||
plan tests => 6;
|
||||
plan tests => 7;
|
||||
}
|
||||
|
||||
my $output;
|
||||
@@ -43,11 +43,14 @@ my $cnf = '/tmp/12346/my.sandbox.cnf';
|
||||
my $cmd = "$trunk/bin/pt-slave-delay -F $cnf h=127.1";
|
||||
|
||||
# 1
|
||||
$output = `$cmd --help`;
|
||||
$output = `$cmd --help 2>&1`;
|
||||
like($output, qr/Prompt for a password/, 'It compiles');
|
||||
|
||||
# Check deprecation warning
|
||||
like($output, qr/This tool is deprecated and will be removed in future releases/, 'Deprecation warning printed') or diag($output);
|
||||
|
||||
# #############################################################################
|
||||
# 2 Issue 149: h is required even with S, for slavehost argument
|
||||
# Issue 149: h is required even with S, for slavehost argument
|
||||
# #############################################################################
|
||||
$output = `$trunk/bin/pt-slave-delay --run-time 1s --delay 1s --interval 1s S=/tmp/12346/mysql_sandbox12346.sock 2>&1`;
|
||||
unlike($output, qr/Missing DSN part 'h'/, 'Does not require h DSN part');
|
||||
@@ -58,34 +61,40 @@ unlike($output, qr/Missing DSN part 'h'/, 'Does not require h DSN part');
|
||||
# easily when you connect to a SLAVE-HOST twice by accident.) To reproduce,
|
||||
# just disable log-bin and log-slave-updates on the slave.
|
||||
# #####1#######################################################################
|
||||
diag(`cp /tmp/12346/my.sandbox.cnf /tmp/12346/my.sandbox.cnf-original`);
|
||||
diag(`sed -i.bak -e '/log-bin/d' -e '/log_slave_updates/d' /tmp/12346/my.sandbox.cnf`);
|
||||
diag(`/tmp/12346/stop >/dev/null`);
|
||||
diag(`/tmp/12346/start >/dev/null`);
|
||||
diag("Sleeping 3 seconds ...");
|
||||
sleep(3);
|
||||
$slave2_dbh->do('STOP SLAVE');
|
||||
$slave2_dbh->do('RESET SLAVE');
|
||||
$slave2_dbh->do('START SLAVE');
|
||||
SKIP: {
|
||||
if ($sandbox_version ge '8.0') {
|
||||
skip 'Binary log is ON by default in 8.0+';
|
||||
}
|
||||
|
||||
# 3
|
||||
$output = `$trunk/bin/pt-slave-delay --delay 1s h=127.1,P=12346,u=msandbox,p=msandbox h=127.1 2>&1`;
|
||||
like(
|
||||
$output,
|
||||
qr/Binary logging is disabled/,
|
||||
'Detects master that is not a master'
|
||||
);
|
||||
diag(`cp /tmp/12346/my.sandbox.cnf /tmp/12346/my.sandbox.cnf-original`);
|
||||
diag(`sed -i.bak -e '/log-bin/d' -e '/log_slave_updates/d' /tmp/12346/my.sandbox.cnf`);
|
||||
diag(`/tmp/12346/stop >/dev/null`);
|
||||
diag(`/tmp/12346/start >/dev/null`);
|
||||
diag("Sleeping 3 seconds ...");
|
||||
sleep(3);
|
||||
$slave2_dbh->do('STOP SLAVE');
|
||||
$slave2_dbh->do('RESET SLAVE');
|
||||
$slave2_dbh->do('START SLAVE');
|
||||
|
||||
diag(`/tmp/12346/stop >/dev/null`);
|
||||
diag(`mv /tmp/12346/my.sandbox.cnf-original /tmp/12346/my.sandbox.cnf`);
|
||||
diag(`/tmp/12346/start >/dev/null`);
|
||||
diag(`/tmp/12346/use -e "set global read_only=1"`);
|
||||
# 3
|
||||
$output = `$trunk/bin/pt-slave-delay --delay 1s h=127.1,P=12346,u=msandbox,p=msandbox h=127.1 2>&1`;
|
||||
like(
|
||||
$output,
|
||||
qr/Binary logging is disabled/,
|
||||
'Detects master that is not a master'
|
||||
);
|
||||
|
||||
diag("Sleeping 3 seconds ...");
|
||||
sleep(3);
|
||||
$slave2_dbh->do('STOP SLAVE');
|
||||
$slave2_dbh->do('RESET SLAVE');
|
||||
$slave2_dbh->do('START SLAVE');
|
||||
diag(`/tmp/12346/stop >/dev/null`);
|
||||
diag(`mv /tmp/12346/my.sandbox.cnf-original /tmp/12346/my.sandbox.cnf`);
|
||||
diag(`/tmp/12346/start >/dev/null`);
|
||||
diag(`/tmp/12346/use -e "set global read_only=1"`);
|
||||
|
||||
diag("Sleeping 3 seconds ...");
|
||||
sleep(3);
|
||||
$slave2_dbh->do('STOP SLAVE');
|
||||
$slave2_dbh->do('RESET SLAVE');
|
||||
$slave2_dbh->do('START SLAVE');
|
||||
}
|
||||
|
||||
# #############################################################################
|
||||
# Check --use-master
|
||||
|
63
t/pt-slave-delay/deprecation.t
Normal file
63
t/pt-slave-delay/deprecation.t
Normal file
@@ -0,0 +1,63 @@
|
||||
#!/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-slave-delay";
|
||||
|
||||
my $dp = new DSNParser(opts=>$dsn_opts);
|
||||
my $sb = new Sandbox(basedir => '/tmp', DSNParser => $dp);
|
||||
my $master_dbh = $sb->get_dbh_for('source');
|
||||
my $slave1_dbh = $sb->get_dbh_for('replica1');
|
||||
my $slave2_dbh = $sb->get_dbh_for('replica2');
|
||||
|
||||
if ($sandbox_version lt '8.1') {
|
||||
plan skip_all => 'Tool is supported.';
|
||||
}
|
||||
|
||||
if ( !$master_dbh ) {
|
||||
plan skip_all => 'Cannot connect to sandbox master';
|
||||
}
|
||||
elsif ( !$slave1_dbh ) {
|
||||
plan skip_all => 'Cannot connect to sandbox slave1';
|
||||
}
|
||||
elsif ( !$slave2_dbh ) {
|
||||
plan skip_all => 'Cannot connect to sandbox slave2';
|
||||
}
|
||||
else {
|
||||
plan tests => 3;
|
||||
}
|
||||
|
||||
my $output;
|
||||
my $cnf = '/tmp/12346/my.sandbox.cnf';
|
||||
my $cmd = "$trunk/bin/pt-slave-delay -F $cnf h=127.1";
|
||||
|
||||
$output = `$cmd 2>&1`;
|
||||
like(
|
||||
$output,
|
||||
qr/This tool does not work with MySQL 8.1 and newer/,
|
||||
'The tool does not work with 8.1 or newer'
|
||||
);
|
||||
|
||||
isnt(
|
||||
$? >> 8,
|
||||
0,
|
||||
"Tool died"
|
||||
);
|
||||
|
||||
# #############################################################################
|
||||
# Done.
|
||||
# #############################################################################
|
||||
$sb->wipe_clean($master_dbh);
|
||||
ok($sb->ok(), "Sandbox servers") or BAIL_OUT(__FILE__ . " broke the sandbox");
|
||||
exit;
|
@@ -20,8 +20,8 @@ my $dp = DSNParser->new(opts => $dsn_opts);
|
||||
my $sb = Sandbox->new(basedir => '/tmp', DSNParser => $dp);
|
||||
my $dbh = $sb->get_dbh_for('replica1');
|
||||
|
||||
if ($sandbox_version ge '5.7') {
|
||||
plan skip_all => 'Use SQL_DELAY';
|
||||
if ($sandbox_version ge '8.1') {
|
||||
plan skip_all => 'Tool is not supported. Use SQL_DELAY';
|
||||
}
|
||||
|
||||
if ( !$dbh ) {
|
||||
|
@@ -20,8 +20,8 @@ my $sb = new Sandbox(basedir => '/tmp', DSNParser => $dp);
|
||||
my $master_dbh = $sb->get_dbh_for('source');
|
||||
my $slave_dbh = $sb->get_dbh_for('replica1');
|
||||
|
||||
if ($sandbox_version ge '5.7') {
|
||||
plan skip_all => 'Use SQL_DELAY';
|
||||
if ($sandbox_version ge '8.1') {
|
||||
plan skip_all => 'Tool is not supported. Use SQL_DELAY';
|
||||
}
|
||||
|
||||
if ( !$master_dbh ) {
|
||||
|
Reference in New Issue
Block a user