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:
Brian Fraser
2012-08-23 03:14:14 -03:00
parent 5ddef54fc8
commit c444384c6c
5 changed files with 334 additions and 44 deletions

View File

@@ -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+)/;