mirror of
https://github.com/percona/percona-toolkit.git
synced 2025-09-24 13:25:01 +00:00
Untested but working first attempt to nibble rows below first lower boundary and above last upper boundary.
This commit is contained in:
@@ -3730,6 +3730,7 @@ sub statements {
|
|||||||
sub boundaries {
|
sub boundaries {
|
||||||
my ($self) = @_;
|
my ($self) = @_;
|
||||||
return {
|
return {
|
||||||
|
first_lower => $self->{first_lower},
|
||||||
lower => $self->{lower},
|
lower => $self->{lower},
|
||||||
upper => $self->{upper},
|
upper => $self->{upper},
|
||||||
next_lower => $self->{next_lower},
|
next_lower => $self->{next_lower},
|
||||||
@@ -3915,7 +3916,8 @@ sub _get_bounds {
|
|||||||
|
|
||||||
my $dbh = $self->{Cxn}->dbh();
|
my $dbh = $self->{Cxn}->dbh();
|
||||||
|
|
||||||
$self->{next_lower} = $dbh->selectrow_arrayref($self->{first_lb_sql});
|
$self->{first_lower} = $dbh->selectrow_arrayref($self->{first_lb_sql});
|
||||||
|
$self->{next_lower} = $self->{first_lower};
|
||||||
MKDEBUG && _d('First lower boundary:', Dumper($self->{next_lower}));
|
MKDEBUG && _d('First lower boundary:', Dumper($self->{next_lower}));
|
||||||
|
|
||||||
$self->{last_upper} = $dbh->selectrow_arrayref($self->{last_ub_sql});
|
$self->{last_upper} = $dbh->selectrow_arrayref($self->{last_ub_sql});
|
||||||
@@ -4015,6 +4017,7 @@ sub DESTROY {
|
|||||||
my ( $self ) = @_;
|
my ( $self ) = @_;
|
||||||
foreach my $key ( keys %$self ) {
|
foreach my $key ( keys %$self ) {
|
||||||
if ( $key =~ m/_sth$/ ) {
|
if ( $key =~ m/_sth$/ ) {
|
||||||
|
MKDEBUG && _d('Finish', $key);
|
||||||
$self->{$key}->finish();
|
$self->{$key}->finish();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -4035,6 +4038,185 @@ sub _d {
|
|||||||
# End NibbleIterator package
|
# End NibbleIterator package
|
||||||
# ###########################################################################
|
# ###########################################################################
|
||||||
|
|
||||||
|
# ###########################################################################
|
||||||
|
# OobNibbleIterator package
|
||||||
|
# This package is a copy without comments from the original. The original
|
||||||
|
# with comments and its test file can be found in the Bazaar repository at,
|
||||||
|
# lib/OobNibbleIterator.pm
|
||||||
|
# t/lib/OobNibbleIterator.t
|
||||||
|
# See https://launchpad.net/percona-toolkit for more information.
|
||||||
|
# ###########################################################################
|
||||||
|
{
|
||||||
|
package OobNibbleIterator;
|
||||||
|
use base 'NibbleIterator';
|
||||||
|
|
||||||
|
use strict;
|
||||||
|
use warnings FATAL => 'all';
|
||||||
|
use English qw(-no_match_vars);
|
||||||
|
use constant MKDEBUG => $ENV{MKDEBUG} || 0;
|
||||||
|
|
||||||
|
use Data::Dumper;
|
||||||
|
$Data::Dumper::Indent = 1;
|
||||||
|
$Data::Dumper::Sortkeys = 1;
|
||||||
|
$Data::Dumper::Quotekeys = 0;
|
||||||
|
|
||||||
|
sub new {
|
||||||
|
my ( $class, %args ) = @_;
|
||||||
|
my @required_args = qw();
|
||||||
|
foreach my $arg ( @required_args ) {
|
||||||
|
die "I need a $arg argument" unless $args{$arg};
|
||||||
|
}
|
||||||
|
|
||||||
|
my $self = $class->SUPER::new(%args);
|
||||||
|
|
||||||
|
my $q = $self->{Quoter};
|
||||||
|
my $o = $self->{OptionParser};
|
||||||
|
my $where = $o->get('where');
|
||||||
|
|
||||||
|
if ( !$self->one_nibble() ) {
|
||||||
|
my $head_sql
|
||||||
|
= ($args{past_dms} || "SELECT ")
|
||||||
|
. ($args{past_select}
|
||||||
|
|| join(', ', map { $q->quote($_) } @{$self->{sql}->{columns}}))
|
||||||
|
. " FROM " . $self->{sql}->{from};
|
||||||
|
|
||||||
|
my $tail_sql
|
||||||
|
= ($where ? " AND ($where)" : '')
|
||||||
|
. " ORDER BY " . $self->{sql}->{order_by};
|
||||||
|
|
||||||
|
my $past_lower_sql
|
||||||
|
= $head_sql
|
||||||
|
. " WHERE " . $self->{sql}->{boundaries}->{'<'}
|
||||||
|
. $tail_sql
|
||||||
|
. " /*past lower chunk*/";
|
||||||
|
MKDEBUG && _d('Past lower statement:', $past_lower_sql);
|
||||||
|
|
||||||
|
my $explain_past_lower_sql
|
||||||
|
= "EXPLAIN SELECT "
|
||||||
|
. ($args{past_select}
|
||||||
|
|| join(', ', map { $q->quote($_) } @{$self->{sql}->{columns}}))
|
||||||
|
. " FROM " . $self->{sql}->{from}
|
||||||
|
. " WHERE " . $self->{sql}->{boundaries}->{'<'}
|
||||||
|
. $tail_sql
|
||||||
|
. " /*explain past lower chunk*/";
|
||||||
|
MKDEBUG && _d('Past lower statement:', $explain_past_lower_sql);
|
||||||
|
|
||||||
|
my $past_upper_sql
|
||||||
|
= $head_sql
|
||||||
|
. " WHERE " . $self->{sql}->{boundaries}->{'>'}
|
||||||
|
. $tail_sql
|
||||||
|
. " /*past upper chunk*/";
|
||||||
|
MKDEBUG && _d('Past upper statement:', $past_upper_sql);
|
||||||
|
|
||||||
|
my $explain_past_upper_sql
|
||||||
|
= "EXPLAIN SELECT "
|
||||||
|
. ($args{past_select}
|
||||||
|
|| join(', ', map { $q->quote($_) } @{$self->{sql}->{columns}}))
|
||||||
|
. " FROM " . $self->{sql}->{from}
|
||||||
|
. " WHERE " . $self->{sql}->{boundaries}->{'>'}
|
||||||
|
. $tail_sql
|
||||||
|
. " /*explain past upper chunk*/";
|
||||||
|
MKDEBUG && _d('Past upper statement:', $explain_past_upper_sql);
|
||||||
|
|
||||||
|
$self->{past_lower_sql} = $past_lower_sql;
|
||||||
|
$self->{past_upper_sql} = $past_upper_sql;
|
||||||
|
$self->{explain_past_lower_sql} = $explain_past_lower_sql;
|
||||||
|
$self->{explain_past_upper_sql} = $explain_past_upper_sql;
|
||||||
|
$self->{past_nibbles} = [qw(lower upper)]; # what we nibble
|
||||||
|
}
|
||||||
|
|
||||||
|
return bless $self, $class;
|
||||||
|
}
|
||||||
|
|
||||||
|
sub more_boundaries {
|
||||||
|
my ($self) = @_;
|
||||||
|
return $self->SUPER::more_boundaries() if $self->{one_nibble};
|
||||||
|
return scalar @{$self->{past_nibbles}} ? 1 : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
sub statements {
|
||||||
|
my ($self) = @_;
|
||||||
|
|
||||||
|
my $sths = $self->SUPER::statements();
|
||||||
|
|
||||||
|
$sths->{past_lower_boundary} = $self->{past_lower_sth};
|
||||||
|
$sths->{past_upper_boundary} = $self->{past_upper_sth};
|
||||||
|
|
||||||
|
return $sths;
|
||||||
|
}
|
||||||
|
|
||||||
|
sub _prepare_sths {
|
||||||
|
my ($self) = @_;
|
||||||
|
MKDEBUG && _d('Preparing boundless statement handles');
|
||||||
|
|
||||||
|
if ( !$self->{one_nibble} ) {
|
||||||
|
my $dbh = $self->{Cxn}->dbh();
|
||||||
|
$self->{past_lower_sth} = $dbh->prepare($self->{past_lower_sql});
|
||||||
|
$self->{past_upper_sth} = $dbh->prepare($self->{past_upper_sql});
|
||||||
|
$self->{explain_past_lower_sth} = $dbh->prepare($self->{explain_past_lower_sql});
|
||||||
|
$self->{explain_past_upper_sth} = $dbh->prepare($self->{explain_past_upper_sql});
|
||||||
|
}
|
||||||
|
|
||||||
|
return $self->SUPER::_prepare_sths();
|
||||||
|
}
|
||||||
|
|
||||||
|
sub _next_boundaries {
|
||||||
|
my ($self) = @_;
|
||||||
|
|
||||||
|
return $self->SUPER::_next_boundaries() unless $self->{no_more_boundaries};
|
||||||
|
|
||||||
|
if ( my $past = shift @{$self->{past_nibbles}} ) {
|
||||||
|
if ( $past eq 'lower' ) {
|
||||||
|
MKDEBUG && _d('Nibbling values below lower boundary');
|
||||||
|
$self->{nibble_sth} = $self->{past_lower_sth};
|
||||||
|
$self->{explain_nibble_sth} = $self->{explain_past_lower_sth};
|
||||||
|
$self->{lower} = [];
|
||||||
|
$self->{upper} = $self->boundaries()->{first_lower};
|
||||||
|
$self->{next_lower} = undef;
|
||||||
|
}
|
||||||
|
elsif ( $past eq 'upper' ) {
|
||||||
|
MKDEBUG && _d('Nibbling values above upper boundary');
|
||||||
|
$self->{nibble_sth} = $self->{past_upper_sth};
|
||||||
|
$self->{explain_nibble_sth} = $self->{explain_past_upper_sth};
|
||||||
|
$self->{lower} = $self->boundaries()->{last_upper};
|
||||||
|
$self->{upper} = [];
|
||||||
|
$self->{next_lower} = undef;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
die "Invalid past nibble: $past";
|
||||||
|
}
|
||||||
|
return 1; # continue nibbling
|
||||||
|
}
|
||||||
|
|
||||||
|
MKDEBUG && _d('Done nibbling past boundaries');
|
||||||
|
return; # stop nibbling
|
||||||
|
}
|
||||||
|
|
||||||
|
sub DESTROY {
|
||||||
|
my ( $self ) = @_;
|
||||||
|
foreach my $key ( keys %$self ) {
|
||||||
|
if ( $key =~ m/_sth$/ ) {
|
||||||
|
MKDEBUG && _d('Finish', $key);
|
||||||
|
$self->{$key}->finish();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
sub _d {
|
||||||
|
my ($package, undef, $line) = caller 0;
|
||||||
|
@_ = map { (my $temp = $_) =~ s/\n/\n# /g; $temp; }
|
||||||
|
map { defined $_ ? $_ : 'undef' }
|
||||||
|
@_;
|
||||||
|
print STDERR "# $package:$line $PID ", join(' ', @_), "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
1;
|
||||||
|
}
|
||||||
|
# ###########################################################################
|
||||||
|
# End OobNibbleIterator package
|
||||||
|
# ###########################################################################
|
||||||
|
|
||||||
# ###########################################################################
|
# ###########################################################################
|
||||||
# Daemon package
|
# Daemon package
|
||||||
# This package is a copy without comments from the original. The original
|
# This package is a copy without comments from the original. The original
|
||||||
@@ -5910,10 +6092,11 @@ sub main {
|
|||||||
# Checksum args and the DMS part of the checksum query for each table.
|
# Checksum args and the DMS part of the checksum query for each table.
|
||||||
# ########################################################################
|
# ########################################################################
|
||||||
my %crc_args = $rc->get_crc_args(dbh => $master_dbh);
|
my %crc_args = $rc->get_crc_args(dbh => $master_dbh);
|
||||||
my $checksum_dms = "REPLACE INTO $repl_table "
|
my $checksum_dml = "REPLACE INTO $repl_table "
|
||||||
. "(db, tbl, chunk, chunk_index,"
|
. "(db, tbl, chunk, chunk_index,"
|
||||||
. " lower_boundary, upper_boundary, this_cnt, this_crc) "
|
. " lower_boundary, upper_boundary, this_cnt, this_crc) "
|
||||||
. "SELECT ?, ?, ?, ?, ?, ?,";
|
. "SELECT ?, ?, ?, ?, ?, ?,";
|
||||||
|
my $past_cols = " COUNT(*), '0'";
|
||||||
|
|
||||||
# ########################################################################
|
# ########################################################################
|
||||||
# Get last chunk for --resume.
|
# Get last chunk for --resume.
|
||||||
@@ -6362,13 +6545,15 @@ sub main {
|
|||||||
);
|
);
|
||||||
my $nibble_iter;
|
my $nibble_iter;
|
||||||
eval {
|
eval {
|
||||||
$nibble_iter = new NibbleIterator(
|
$nibble_iter = new OobNibbleIterator(
|
||||||
Cxn => $master_cxn,
|
Cxn => $master_cxn,
|
||||||
tbl => $tbl,
|
tbl => $tbl,
|
||||||
chunk_size => $tbl->{chunk_size},
|
chunk_size => $tbl->{chunk_size},
|
||||||
chunk_index => $o->get('chunk-index'),
|
chunk_index => $o->get('chunk-index'),
|
||||||
dms => $checksum_dms,
|
dms => $checksum_dml,
|
||||||
select => $checksum_cols,
|
select => $checksum_cols,
|
||||||
|
past_dms => $checksum_dml,
|
||||||
|
past_select => $past_cols,
|
||||||
callbacks => $callbacks,
|
callbacks => $callbacks,
|
||||||
OptionParser => $o,
|
OptionParser => $o,
|
||||||
Quoter => $q,
|
Quoter => $q,
|
||||||
|
@@ -20,6 +20,10 @@ $ENV{PERCONA_TOOLKIT_TEST_USE_DSN_NAMES} = 1;
|
|||||||
use Data::Dumper;
|
use Data::Dumper;
|
||||||
use PerconaTest;
|
use PerconaTest;
|
||||||
use Sandbox;
|
use Sandbox;
|
||||||
|
|
||||||
|
# Fix @INC because pt-table-checksum uses subclass OobNibbleIterator.
|
||||||
|
shift @INC; # our unshift (above)
|
||||||
|
shift @INC; # PerconaTest's unshift
|
||||||
require "$trunk/bin/pt-table-checksum";
|
require "$trunk/bin/pt-table-checksum";
|
||||||
|
|
||||||
my $dp = new DSNParser(opts=>$dsn_opts);
|
my $dp = new DSNParser(opts=>$dsn_opts);
|
||||||
|
Reference in New Issue
Block a user