merge branch daniel

This commit is contained in:
Kenny Gryp
2014-05-29 00:18:57 +02:00
5 changed files with 174 additions and 143 deletions

View File

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

View File

@@ -379,6 +379,7 @@ sub verify_test_data {
# Diff the two sets of checksums: host to master (ref). # Diff the two sets of checksums: host to master (ref).
my @diffs; my @diffs;
foreach my $c ( @checksums ) { foreach my $c ( @checksums ) {
next unless $c->{checksum};
if ( $c->{checksum} ne $ref->{$c->{table}}->{checksum} ) { if ( $c->{checksum} ne $ref->{$c->{table}}->{checksum} ) {
push @diffs, $c->{table}; push @diffs, $c->{table};
} }

View File

@@ -315,6 +315,8 @@ case $opt in
fi fi
if [ $? -eq 0 -a "$MYSQL_VERSION" '>' "4.1" ]; then if [ $? -eq 0 -a "$MYSQL_VERSION" '>' "4.1" ]; then
SAKILA=${SAKILA:-1}
if [ $SAKILA -eq 1 ]; then
echo -n "Loading sakila database... " echo -n "Loading sakila database... "
./load-sakila-db 12345 "${2:-""}" ./load-sakila-db 12345 "${2:-""}"
exit_status=$((exit_status | $?)) exit_status=$((exit_status | $?))
@@ -323,6 +325,7 @@ case $opt in
else else
echo "OK" echo "OK"
fi fi
fi
# Create percona_test db and checksum all the tables. # Create percona_test db and checksum all the tables.
../util/checksum-test-dataset ../util/checksum-test-dataset

View File

@@ -16,69 +16,119 @@ use Sandbox;
require "$trunk/bin/pt-slave-restart"; require "$trunk/bin/pt-slave-restart";
if ( $sandbox_version lt '5.6' ) { if ( $sandbox_version lt '5.6' ) {
plan skip_all => 'MySQL Version ' . $sandbox_version plan skip_all => "Requires MySQL 5.6";
. ' < 5.6, GTID is not available, skipping tests';
} }
diag("Stopping/reconfiguring/restarting sandboxes 12345, 12346 and 12347"); diag(`SAKILA=0 GTID=1 $trunk/sandbox/test-env restart`);
diag(`$trunk/sandbox/test-env stop >/dev/null`);
diag(`GTID=1 $trunk/sandbox/test-env start >/dev/null`);
my $dp = new DSNParser(opts=>$dsn_opts); my $dp = new DSNParser(opts=>$dsn_opts);
my $sb = new Sandbox(basedir => '/tmp', DSNParser => $dp); my $sb = new Sandbox(basedir => '/tmp', DSNParser => $dp);
my $master_dbh = $sb->get_dbh_for('master'); my $master_dbh = $sb->get_dbh_for('master');
my $slave_dbh = $sb->get_dbh_for('slave1'); my $slave1_dbh = $sb->get_dbh_for('slave1');
my $slave2_dbh = $sb->get_dbh_for('slave2'); my $slave2_dbh = $sb->get_dbh_for('slave2');
if ( !$master_dbh ) { if ( !$master_dbh ) {
plan skip_all => 'Cannot connect to sandbox master'; plan skip_all => 'Cannot connect to sandbox master';
} }
elsif ( !$slave_dbh ) { elsif ( !$slave1_dbh ) {
plan skip_all => 'Cannot connect to sandbox slave1'; plan skip_all => 'Cannot connect to sandbox slave1';
} }
elsif ( !$slave2_dbh ) { elsif ( !$slave2_dbh ) {
plan skip_all => 'Cannot connect to sandbox slave2'; plan skip_all => 'Cannot connect to sandbox slave2';
} }
my $slave1_dsn = $sb->dsn_for("slave1");
my $slave2_dsn = $sb->dsn_for("slave2");
my $pid_file = "/tmp/pt-slave-restart-test-$PID.pid";
my $log_file = "/tmp/pt-slave-restart-test-$PID.log";
my $cmd = "$trunk/bin/pt-slave-restart --daemonize --run-time 5 --max-sleep .25 --pid $pid_file --log $log_file";
sub start {
my ( $extra ) = @_;
stop() or return;
system "$cmd $extra";
PerconaTest::wait_for_files($pid_file);
}
sub stop() {
return 1 if !is_running();
diag(`$trunk/bin/pt-slave-restart --stop -q >/dev/null 2>&1 &`);
wait_until(sub { !-f $pid_file }, 0.3, 2);
diag(`rm -f /tmp/pt-slave-restart-sentinel`);
return is_running() ? 0 : 1;
}
sub is_running {
chomp(my $running = `ps -eaf | grep -v grep | grep '$cmd'`);
if (!-f $pid_file && !$running) {
return 0;
} elsif (-f $pid_file && !$running) {
diag(`rm -f $pid_file`);
return 0;
}
return 1;
}
sub wait_repl_broke {
my $dbh = shift;
return wait_until(
sub {
my $row = $dbh->selectrow_hashref('show slave status');
return $row->{last_sql_errno};
}
);
}
sub wait_repl_ok {
my $dbh = shift;
wait_until(
sub {
my $row = $dbh->selectrow_hashref('show slave status');
return $row->{last_sql_errno} == 0;
},
0.30,
5,
);
}
# ############################################################################# # #############################################################################
# basic test to see if restart works # Basic test to see if restart works with GTID.
# ############################################################################# # #############################################################################
$master_dbh->do('DROP DATABASE IF EXISTS test'); $master_dbh->do('DROP DATABASE IF EXISTS test');
$master_dbh->do('CREATE DATABASE test'); $master_dbh->do('CREATE DATABASE test');
$master_dbh->do('CREATE TABLE test.t (a INT)'); $master_dbh->do('CREATE TABLE test.t (a INT)');
$sb->wait_for_slaves; $sb->wait_for_slaves;
# Bust replication # Bust replication
$slave_dbh->do('DROP TABLE test.t'); $slave1_dbh->do('DROP TABLE test.t');
$master_dbh->do('INSERT INTO test.t SELECT 1'); $master_dbh->do('INSERT INTO test.t SELECT 1');
wait_until( wait_repl_broke($slave1_dbh) or die "Failed to break replication";
sub {
my $row = $slave_dbh->selectrow_hashref('show slave status');
return $row->{last_sql_errno};
}
);
my $r = $slave_dbh->selectrow_hashref('show slave status'); my $r = $slave1_dbh->selectrow_hashref('show slave status');
like($r->{last_error}, qr/Table 'test.t' doesn't exist'/, 'slave: Replication broke'); like($r->{last_error}, qr/Table 'test.t' doesn't exist'/, 'slave: Replication broke');
# Start an instance # Start pt-slave-restart and wait up to 5s for it to fix replication
diag(`$trunk/bin/pt-slave-restart --max-sleep .25 -h 127.0.0.1 -P 12346 -u msandbox -p msandbox --daemonize --pid /tmp/pt-slave-restart.pid --log /tmp/pt-slave-restart.log`); # (it should take < 1s but tests can be really slow sometimes).
sleep 1; start("$slave1_dsn") or die "Failed to start pt-slave-restart";
wait_repl_ok($slave1_dbh);
$r = $slave_dbh->selectrow_hashref('show slave status'); # Check if replication is fixed.
like($r->{last_errno}, qr/^0$/, 'slave: event is not skipped successfully'); $r = $slave1_dbh->selectrow_hashref('show slave status');
like(
$r->{last_errno},
qr/^0$/,
'Event is skipped',
) or BAIL_OUT("Replication is broken");
# Stop pt-slave-restart.
diag(`$trunk/bin/pt-slave-restart --stop -q`); stop() or die "Failed to stop pt-slave-restart";
sleep 1;
my $output = `ps -eaf | grep pt-slave-restart | grep -v grep`;
unlike($output, qr/pt-slave-restart --max/, 'slave: stopped pt-slave-restart successfully');
diag(`rm -f /tmp/pt-slave-re*`);
# ############################################################################# # #############################################################################
# test the slave of the master # Test the slave of the master.
# ############################################################################# # #############################################################################
$master_dbh->do('DROP DATABASE IF EXISTS test'); $master_dbh->do('DROP DATABASE IF EXISTS test');
$master_dbh->do('CREATE DATABASE test'); $master_dbh->do('CREATE DATABASE test');
$master_dbh->do('CREATE TABLE test.t (a INT)'); $master_dbh->do('CREATE TABLE test.t (a INT)');
@@ -87,12 +137,7 @@ $sb->wait_for_slaves;
# Bust replication # Bust replication
$slave2_dbh->do('DROP TABLE test.t'); $slave2_dbh->do('DROP TABLE test.t');
$master_dbh->do('INSERT INTO test.t SELECT 1'); $master_dbh->do('INSERT INTO test.t SELECT 1');
wait_until( wait_repl_broke($slave2_dbh) or die "Failed to break replication";
sub {
my $row = $slave2_dbh->selectrow_hashref('show slave status');
return $row->{last_sql_errno};
}
);
# fetch the master uuid, which is the machine we need to skip an event from # fetch the master uuid, which is the machine we need to skip an event from
$r = $master_dbh->selectrow_hashref('select @@GLOBAL.server_uuid as uuid'); $r = $master_dbh->selectrow_hashref('select @@GLOBAL.server_uuid as uuid');
@@ -102,22 +147,22 @@ $r = $slave2_dbh->selectrow_hashref('show slave status');
like($r->{last_error}, qr/Table 'test.t' doesn't exist'/, 'slaveofslave: Replication broke'); like($r->{last_error}, qr/Table 'test.t' doesn't exist'/, 'slaveofslave: Replication broke');
# Start an instance # Start an instance
diag(`$trunk/bin/pt-slave-restart --skip-gtid-uuid=$uuid --max-sleep .25 -h 127.0.0.1 -P 12347 -u msandbox -p msandbox --daemonize --pid /tmp/pt-slave-restart.pid --log /tmp/pt-slave-restart.log`); start("--master-uuid=$uuid $slave2_dsn") or die;
sleep 1; wait_repl_ok($slave2_dbh);
$r = $slave2_dbh->selectrow_hashref('show slave status'); $r = $slave2_dbh->selectrow_hashref('show slave status');
like($r->{last_errno}, qr/^0$/, 'slaveofslave: event is not skipped successfully'); like(
$r->{last_errno},
qr/^0$/,
'Skips event from master on slave2'
) or BAIL_OUT("Replication is broken");
stop() or die "Failed to stop pt-slave-restart";
diag(`$trunk/bin/pt-slave-restart --stop -q`);
sleep 1;
$output = `ps -eaf | grep pt-slave-restart | grep -v grep`;
unlike($output, qr/pt-slave-restart --max/, 'slaveofslave: stopped pt-slave-restart successfully');
diag(`rm -f /tmp/pt-slave-re*`);
# ############################################################################# # #############################################################################
# test skipping 2 events in a row. # Test skipping 2 events in a row.
# ############################################################################# # #############################################################################
$master_dbh->do('DROP DATABASE IF EXISTS test'); $master_dbh->do('DROP DATABASE IF EXISTS test');
$master_dbh->do('CREATE DATABASE test'); $master_dbh->do('CREATE DATABASE test');
$master_dbh->do('CREATE TABLE test.t (a INT)'); $master_dbh->do('CREATE TABLE test.t (a INT)');
@@ -127,12 +172,7 @@ $sb->wait_for_slaves;
$slave2_dbh->do('DROP TABLE test.t'); $slave2_dbh->do('DROP TABLE test.t');
$master_dbh->do('INSERT INTO test.t SELECT 1'); $master_dbh->do('INSERT INTO test.t SELECT 1');
$master_dbh->do('INSERT INTO test.t SELECT 1'); $master_dbh->do('INSERT INTO test.t SELECT 1');
wait_until( wait_repl_broke($slave2_dbh) or die "Failed to break replication";
sub {
my $row = $slave2_dbh->selectrow_hashref('show slave status');
return $row->{last_sql_errno};
}
);
# fetch the master uuid, which is the machine we need to skip an event from # fetch the master uuid, which is the machine we need to skip an event from
$r = $master_dbh->selectrow_hashref('select @@GLOBAL.server_uuid as uuid'); $r = $master_dbh->selectrow_hashref('select @@GLOBAL.server_uuid as uuid');
@@ -142,25 +182,22 @@ $r = $slave2_dbh->selectrow_hashref('show slave status');
like($r->{last_error}, qr/Table 'test.t' doesn't exist'/, 'slaveofslaveskip2: Replication broke'); like($r->{last_error}, qr/Table 'test.t' doesn't exist'/, 'slaveofslaveskip2: Replication broke');
# Start an instance # Start an instance
diag(`$trunk/bin/pt-slave-restart --skip-count=2 --skip-gtid-uuid=$uuid --max-sleep .25 -h 127.0.0.1 -P 12347 -u msandbox -p msandbox --daemonize --pid /tmp/pt-slave-restart.pid --log /tmp/pt-slave-restart.log`); start("--skip-count=2 --master-uuid=$uuid $slave2_dsn") or die;
sleep 1; wait_repl_ok($slave2_dbh);
$r = $slave2_dbh->selectrow_hashref('show slave status'); $r = $slave2_dbh->selectrow_hashref('show slave status');
like($r->{last_errno}, qr/^0$/, 'slaveofslaveskip2: event is not skipped successfully'); like(
$r->{last_errno},
qr/^0$/,
'Skips multiple events'
) or BAIL_OUT("Replication is broken");
stop() or die "Failed to stop pt-slave-restart";
diag(`$trunk/bin/pt-slave-restart --stop -q`);
sleep 1;
$output = `ps -eaf | grep pt-slave-restart | grep -v grep`;
unlike($output, qr/pt-slave-restart --max/, 'slaveofslaveskip2: stopped pt-slave-restart successfully');
diag(`rm -f /tmp/pt-slave-re*`);
# ############################################################################# # #############################################################################
# Done. # Done.
# ############################################################################# # #############################################################################
diag(`rm -f /tmp/pt-slave-re*`); diag(`rm -f $pid_file $log_file >/dev/null`);
diag(`$trunk/sandbox/test-env stop >/dev/null`); diag(`$trunk/sandbox/test-env restart`);
diag(`$trunk/sandbox/test-env start >/dev/null`);
ok($sb->ok(), "Sandbox servers") or BAIL_OUT(__FILE__ . " broke the sandbox"); ok($sb->ok(), "Sandbox servers") or BAIL_OUT(__FILE__ . " broke the sandbox");
done_testing; done_testing;

View File

@@ -61,6 +61,7 @@ my $sql = "CHECKSUM TABLES "
. join(", ", map { "sakila.$_" } @tables_in_sakila); . join(", ", map { "sakila.$_" } @tables_in_sakila);
my @checksums = @{$dbh->selectall_arrayref($sql, {Slice => {} })}; my @checksums = @{$dbh->selectall_arrayref($sql, {Slice => {} })};
foreach my $c ( @checksums ) { foreach my $c ( @checksums ) {
next unless $c->{Checksum};
$dbh->do("INSERT INTO percona_test.checksums(db_tbl, checksum) $dbh->do("INSERT INTO percona_test.checksums(db_tbl, checksum)
VALUES('$c->{Table}', $c->{Checksum})"); VALUES('$c->{Table}', $c->{Checksum})");
} }