mirror of
https://github.com/percona/percona-toolkit.git
synced 2025-10-18 08:24:06 +00:00
Fix for 1009510 and 1039569: pt-table-checksum doesn't check that tables exist on all replicas / shouldn't die if it can't create db/table
This commit is contained in:
@@ -38,16 +38,20 @@ $Data::Dumper::Indent = 1;
|
||||
$Data::Dumper::Sortkeys = 1;
|
||||
$Data::Dumper::Quotekeys = 0;
|
||||
|
||||
local $EVAL_ERROR;
|
||||
eval {
|
||||
require Quoter;
|
||||
};
|
||||
|
||||
sub new {
|
||||
my ( $class, %args ) = @_;
|
||||
my @required_args = qw(Quoter);
|
||||
foreach my $arg ( @required_args ) {
|
||||
die "I need a $arg argument" unless $args{$arg};
|
||||
}
|
||||
my $self = { %args };
|
||||
$self->{Quoter} ||= Quoter->new();
|
||||
return bless $self, $class;
|
||||
}
|
||||
|
||||
sub Quoter { shift->{Quoter} }
|
||||
|
||||
sub get_create_table {
|
||||
my ( $self, $dbh, $db, $tbl ) = @_;
|
||||
die "I need a dbh parameter" unless $dbh;
|
||||
@@ -362,6 +366,84 @@ sub check_table {
|
||||
return 1;
|
||||
}
|
||||
|
||||
# Required args:
|
||||
# * slave_tbl hashref:
|
||||
# * master_tbl hashref: table struct to check against
|
||||
# * slave_name scalar: name of the slave, for error messages
|
||||
# Returns: bool
|
||||
# Can die: yes
|
||||
# check_table_against_slave() checks the given table struct against
|
||||
# a slave dbh; It should only be called after checking that the table
|
||||
# exists in the slave (through check_table()). It will die if the table
|
||||
# in the slave doesn't have any of the columns in the master, and warn
|
||||
# if there are any extra columns in the slave.
|
||||
|
||||
sub check_table_against_slave {
|
||||
my ($self, %args) = @_;
|
||||
|
||||
my @required_args = qw(tbl_name slave_tbl slave_name master_tbl);
|
||||
foreach my $arg ( @required_args ) {
|
||||
die "I need a $arg argument" unless $args{$arg};
|
||||
}
|
||||
my ($tbl_name, $slave_tbl, $slave_name, $master_tbl) = @args{@required_args};
|
||||
|
||||
my $columns_in_slave = { map { $_ => 1 } @{$slave_tbl->{cols}} };
|
||||
my $columns_in_master = { map { $_ => 1 } @{$master_tbl->{cols}} };
|
||||
|
||||
my @extra_columns_in_slave;
|
||||
for my $column (keys %$columns_in_slave) {
|
||||
if ( $columns_in_master->{$column} ) {
|
||||
$columns_in_master->{$column}++
|
||||
}
|
||||
else {
|
||||
push @extra_columns_in_slave, $column;
|
||||
}
|
||||
}
|
||||
|
||||
my @not_in_slave = grep { $columns_in_master->{$_} != 2 }
|
||||
keys %$columns_in_master;
|
||||
|
||||
die "Table $tbl_name in $slave_name differs from master: "
|
||||
. "Columns @not_in_slave are missing\n "
|
||||
if @not_in_slave;
|
||||
|
||||
print STDERR "Table $tbl_name in $slave_name has more columns than "
|
||||
. "its master: @extra_columns_in_slave\n"
|
||||
if @extra_columns_in_slave;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
sub check_table_against_slaves {
|
||||
my ($self, %args) = @_;
|
||||
|
||||
my @required_args = qw(tbl_struct db table slaves);
|
||||
foreach my $arg ( @required_args ) {
|
||||
die "I need a $arg argument" unless $args{$arg};
|
||||
}
|
||||
|
||||
my ($tbl_struct, $db, $tbl, $slaves) = @args{@required_args};
|
||||
|
||||
for my $slave_cxn (@$slaves) {
|
||||
my $slave_has_table = $self->check_table(
|
||||
dbh => $slave_cxn->dbh(),
|
||||
db => $db,
|
||||
tbl => $tbl,
|
||||
);
|
||||
die "Table $db.$tbl doesn't exist in slave " . $slave_cxn->name()
|
||||
unless $slave_has_table;
|
||||
|
||||
my $ddl = $self->get_create_table( $slave_cxn->dbh, $db, $tbl );
|
||||
my $slave_tbl = $self->parse( $ddl );
|
||||
$self->check_table_against_slave(
|
||||
tbl_name => "$db.$tbl",
|
||||
master_tbl => $tbl_struct,
|
||||
slave_tbl => $slave_tbl,
|
||||
slave_name => $slave_cxn->name(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
sub get_engine {
|
||||
my ( $self, $ddl, $opts ) = @_;
|
||||
my ( $engine ) = $ddl =~ m/\).*?(?:ENGINE|TYPE)=(\w+)/;
|
||||
|
Reference in New Issue
Block a user