Compare commits

...

1 Commits

Author SHA1 Message Date
Carlos Salguero
70c6c0be7f PT-1585 Added --force-nibbling in pt-tc 2018-07-25 16:09:37 -03:00
5 changed files with 135 additions and 0 deletions

View File

@@ -5838,6 +5838,7 @@ sub can_nibble {
my $one_nibble = !defined $args{one_nibble} || $args{one_nibble}
? $row_est <= $chunk_size * $chunk_size_limit
: 0;
PTDEBUG && _d('One nibble:', $one_nibble ? 'yes' : 'no');
if ( $args{resume}
@@ -5852,6 +5853,16 @@ sub can_nibble {
die "There is no good index and the table is oversized.";
}
if ($o->has('force-nibbling') && $o->get('force-nibbling')) {
my @nibbling_tables = split(/,/, $o->get('force-nibbling'));
my @table_in_list = grep (/$tbl->{tbl}/, @nibbling_tables);
if (@table_in_list && $index && $row_est >= 2) {
PTDEBUG && _d("Disabling one nibble for the entire table");
$one_nibble = 0;
}
}
my $pause_file = ($o->has('pause-file') && $o->get('pause-file')) || undef;
return {

View File

@@ -6689,6 +6689,7 @@ sub can_nibble {
my $one_nibble = !defined $args{one_nibble} || $args{one_nibble}
? $row_est <= $chunk_size * $chunk_size_limit
: 0;
PTDEBUG && _d('One nibble:', $one_nibble ? 'yes' : 'no');
if ( $args{resume}
@@ -6703,6 +6704,16 @@ sub can_nibble {
die "There is no good index and the table is oversized.";
}
if ($o->has('force-nibbling') && $o->get('force-nibbling')) {
my @nibbling_tables = split(/,/, $o->get('force-nibbling'));
my @table_in_list = grep (/$tbl->{tbl}/, @nibbling_tables);
if (@table_in_list && $index && $row_est >= 2) {
PTDEBUG && _d("Disabling one nibble for the entire table");
$one_nibble = 0;
}
}
my $pause_file = ($o->has('pause-file') && $o->get('pause-file')) || undef;
return {
@@ -13262,6 +13273,16 @@ the values are converted to strings by the CONCAT() function, and MySQL chooses
the string representation. If you specify a value of 2, for example, then the
values 1.008 and 1.009 will be rounded to 1.01, and will checksum as equal.
=item --force-nibbling
type: string
Comma sepatered list of tables on which we want to force nibbling instead of
checksuming the whole table in only one chunk,
In some cases, MySQL returns a wrong estimate about number of rows in a table
and NibbleIterator is trying to process huge tables in a single chunk.
This parameter disable one nibble checksums for the specified tables.
=item --function
type: string

View File

@@ -495,6 +495,8 @@ sub can_nibble {
my $one_nibble = !defined $args{one_nibble} || $args{one_nibble}
? $row_est <= $chunk_size * $chunk_size_limit
: 0;
#
PTDEBUG && _d('One nibble:', $one_nibble ? 'yes' : 'no');
# Special case: we're resuming and there's no boundaries, so the table
@@ -512,6 +514,23 @@ sub can_nibble {
die "There is no good index and the table is oversized.";
}
# In some cases, MySQL returns a wrong estimate about number of rows in a table
# and NibbleIterator is trying to process huge tables in a single chunk.
# This parameter disable one nibble.
# See https://jira.percona.com/browse/PT-1585
# This function should work on all scenarios so, to prevent trying to nibble on empty
# (or really really small) tables, we need to ensure tha table has an index and it has
# at least 2 rows, otherwise there is no way to split only one row into chunks.
if ($o->has('force-nibbling') && $o->get('force-nibbling')) {
my @nibbling_tables = split(/,/, $o->get('force-nibbling'));
my @table_in_list = grep (/$tbl->{tbl}/, @nibbling_tables);
if (@table_in_list && $index && $row_est >= 2) {
PTDEBUG && _d("Disabling one nibble for the entire table");
$one_nibble = 0;
}
}
# The table can be nibbled if this point is reached, else we would have
# died earlier. Return some values about nibbling the table.
my $pause_file = ($o->has('pause-file') && $o->get('pause-file')) || undef;

View File

@@ -0,0 +1,75 @@
#!/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;
use SqlModes;
require "$trunk/bin/pt-table-checksum";
my $dp = new DSNParser(opts=>$dsn_opts);
my $sb = new Sandbox(basedir => '/tmp', DSNParser => $dp);
my $dbh = $sb->get_dbh_for('master');
if ( !$dbh ) {
plan skip_all => 'Cannot connect to sandbox master';
}
else {
plan tests => 3;
}
diag("loading samples");
#$sb->load_file('master', 't/pt-table-checksum/samples/pt-226.sql');
$sb->load_file('master', 't/pt-table-checksum/samples/pt-1585.sql');
my $num_rows = 2000;
diag(`util/mysql_random_data_load --host=127.0.0.1 --port=12345 --user=msandbox --password=msandbox test t1 $num_rows`);
diag("$num_rows sample rows loaded");
# The sandbox servers run with lock_wait_timeout=3 and it's not dynamic
# so we need to specify --set-vars innodb_lock_wait_timeout=3 else the tool will die.
# And --max-load "" prevents waiting for status variables.
my $master_dsn = $sb->dsn_for('master');
my @args = ($master_dsn, "--set-vars", "innodb_lock_wait_timeout=50", "--force-nibbling");
my $output;
my $exit_status;
warn @args;
$ENV{PTDEBUG} = 1;
# Test #1
$output = output(
sub { $exit_status = pt_table_checksum::main(@args) },
stderr => 1,
);
delete $ENV{PTDEBUG};
is(
$exit_status,
0,
"PT-226 SET binlog_format='STATEMENT' exit status",
);
like(
$output,
qr/1\s+100\s+0\s+1\s+0\s+.*test.joinit/,
"PT-226 table joinit has differences",
);
$dbh->do('SET GLOBAL binlog_format="STATEMENT"');
# #############################################################################
# Done.
# #############################################################################
$sb->wipe_clean($dbh);
ok($sb->ok(), "Sandbox servers") or BAIL_OUT(__FILE__ . " broke the sandbox");
exit;

View File

@@ -0,0 +1,9 @@
DROP DATABASE IF EXISTS test;
CREATE DATABASE test;
USE test;
CREATE TABLE `test`.`t1` (
id INT AUTO_INCREMENT PRIMARY KEY NOT NULL,
f1 INT
) Engine=InnoDB CHARSET=utf8;