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} my $one_nibble = !defined $args{one_nibble} || $args{one_nibble}
? $row_est <= $chunk_size * $chunk_size_limit ? $row_est <= $chunk_size * $chunk_size_limit
: 0; : 0;
PTDEBUG && _d('One nibble:', $one_nibble ? 'yes' : 'no'); PTDEBUG && _d('One nibble:', $one_nibble ? 'yes' : 'no');
if ( $args{resume} if ( $args{resume}
@@ -5852,6 +5853,16 @@ sub can_nibble {
die "There is no good index and the table is oversized."; 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; my $pause_file = ($o->has('pause-file') && $o->get('pause-file')) || undef;
return { return {

View File

@@ -6689,6 +6689,7 @@ sub can_nibble {
my $one_nibble = !defined $args{one_nibble} || $args{one_nibble} my $one_nibble = !defined $args{one_nibble} || $args{one_nibble}
? $row_est <= $chunk_size * $chunk_size_limit ? $row_est <= $chunk_size * $chunk_size_limit
: 0; : 0;
PTDEBUG && _d('One nibble:', $one_nibble ? 'yes' : 'no'); PTDEBUG && _d('One nibble:', $one_nibble ? 'yes' : 'no');
if ( $args{resume} if ( $args{resume}
@@ -6703,6 +6704,16 @@ sub can_nibble {
die "There is no good index and the table is oversized."; 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; my $pause_file = ($o->has('pause-file') && $o->get('pause-file')) || undef;
return { 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 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. 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 =item --function
type: string type: string

View File

@@ -495,6 +495,8 @@ sub can_nibble {
my $one_nibble = !defined $args{one_nibble} || $args{one_nibble} my $one_nibble = !defined $args{one_nibble} || $args{one_nibble}
? $row_est <= $chunk_size * $chunk_size_limit ? $row_est <= $chunk_size * $chunk_size_limit
: 0; : 0;
#
PTDEBUG && _d('One nibble:', $one_nibble ? 'yes' : 'no'); PTDEBUG && _d('One nibble:', $one_nibble ? 'yes' : 'no');
# Special case: we're resuming and there's no boundaries, so the table # 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."; 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 # The table can be nibbled if this point is reached, else we would have
# died earlier. Return some values about nibbling the table. # died earlier. Return some values about nibbling the table.
my $pause_file = ($o->has('pause-file') && $o->get('pause-file')) || undef; 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;