Add critical load to MySQLStatusWaiter.pm and pt-osc. Clean up the tool's docu.

This commit is contained in:
Daniel Nichter
2012-03-27 19:17:17 -06:00
parent 4c542a71fc
commit 02b3574582
3 changed files with 141 additions and 65 deletions

View File

@@ -3684,18 +3684,31 @@ use constant PTDEBUG => $ENV{PTDEBUG} || 0;
sub new {
my ( $class, %args ) = @_;
my @required_args = qw(spec get_status sleep oktorun);
my @required_args = qw(max_spec get_status sleep oktorun);
foreach my $arg ( @required_args ) {
die "I need a $arg argument" unless defined $args{$arg};
}
my $max_val_for = _parse_spec(%args);
PTDEBUG && _d('Parsing spec for max thresholds');
my $max_val_for = _parse_spec(
spec => $args{max_spec},
get_status => $args{get_status},
threshold_factor => 0.2, # +20%
);
PTDEBUG && _d('Parsing spec for critical thresholds');
my $critical_val_for = _parse_spec(
spec => $args{critical_spec} || [],
get_status => $args{get_status},
threshold_factor => 1.0, # double (x2; +100%)
);
my $self = {
get_status => $args{get_status},
sleep => $args{sleep},
oktorun => $args{oktorun},
max_val_for => $max_val_for,
get_status => $args{get_status},
sleep => $args{sleep},
oktorun => $args{oktorun},
max_val_for => $max_val_for,
critical_val_for => $critical_val_for,
};
return bless $self, $class;
@@ -3709,10 +3722,8 @@ sub _parse_spec {
}
my ($spec, $get_status) = @args{@required_args};
if ( !@$spec ) {
PTDEBUG && _d('No spec, disabling status var waits');
return;
}
return unless $spec && scalar @$spec;
my $threshold_factor = $args{threshold_factor} || 0.20;
my %max_val_for;
foreach my $var_val ( @$spec ) {
@@ -3721,7 +3732,7 @@ sub _parse_spec {
if ( !$val ) {
my $init_val = $get_status->($var);
PTDEBUG && _d('Initial', $var, 'value:', $init_val);
$val = int(($init_val * .20) + $init_val);
$val = int(($init_val * $threshold_factor) + $init_val);
}
PTDEBUG && _d('Wait if', $var, '>=', $val);
$max_val_for{$var} = $val;
@@ -3735,6 +3746,11 @@ sub max_values {
return $self->{max_val_for};
}
sub critical_values {
my ($self) = @_;
return $self->{critical_val_for};
}
sub wait {
my ( $self, %args ) = @_;
@@ -3745,7 +3761,7 @@ sub wait {
my $oktorun = $self->{oktorun};
my $get_status = $self->{get_status};
my $sleep = $self->{sleep};
my %vals_too_high = %{$self->{max_val_for}};
my $pr_callback;
if ( $pr ) {
@@ -3769,6 +3785,12 @@ sub wait {
foreach my $var ( sort keys %vals_too_high ) {
my $val = $get_status->($var);
PTDEBUG && _d($var, '=', $val);
if ( $val
&& exists $self->{critical_val_for}->{$var}
&& $val >= $self->{critical_val_for}->{$var} ) {
die "$var=$val exceeds its critical threshold "
. "$self->{critical_val_for}->{$var}\n";
}
if ( !$val || $val >= $self->{max_val_for}->{$var} ) {
$vals_too_high{$var} = $val;
}
@@ -5146,10 +5168,11 @@ sub main {
}
$sys_load = new MySQLStatusWaiter(
spec => $o->get('max-load'),
get_status => $get_status,
oktorun => sub { return $oktorun },
sleep => $sleep,
max_spec => $o->get('max-load'),
critical_spec => $o->get('critical-load'),
get_status => $get_status,
oktorun => sub { return $oktorun },
sleep => $sleep,
);
if ( $o->get('progress') ) {
@@ -6547,7 +6570,7 @@ pt-online-schema-change - Perform online, non-blocking table schema changes.
=head1 SYNOPSIS
Usage: pt-online-schema-change [OPTION...] DSN
Usage: pt-online-schema-change [OPTIONS] DSN
BARON: NOTE we should say that you ought not to use 'rename' in --alter or the
new table won't exist and the tool will fail.
@@ -6560,20 +6583,13 @@ Change the table's engine to InnoDB:
pt-online-schema-change \
h=127.1,t=db.tbl \
--alter "ENGINE=InnoDB" \
--drop-old-table
Rebuild but do not alter the table, and keep the temporary table:
pt-online-schema-change h=127.1,t=db.tbl
--alter "ENGINE=InnoDB"
Add column to parent table, update child table foreign key constraints:
pt-online-schema-change \
h=127.1,D=db,t=parent \
--alter "ADD COLUMN (foo INT)" \
--child-tables child1,child2 \
--update-foreign-keys-method drop_swap
--alter "ADD COLUMN (foo INT)"
=head1 RISKS
@@ -6666,13 +6682,12 @@ Here are options related to each phase:
1. --alter
2. (none)
3. --chunk-size, --sleep
3. --chunk-size
4. (none)
5. --[no]swap-tables
6. --drop-old-table
6. --[no]drop-old-table
Options L<"--check-tables-and-exit"> and L<"--print"> are helpful to see what
the tool might do before actually doing it.
L<"--print"> is helpful to see what the tool might do before actually doing it.
=head1 REPLICATION
@@ -6772,14 +6787,6 @@ replicas. If you don't want to monitor ALL replicas, but you want more than
just one replica to be monitored, then use the DSN option to the
L<"--recursion-method"> option instead of this option.
=item --check-tables-and-exit
Check that the table can be altered then exit; do not alter the table.
If you just want to see that the tool can/will work for the given table,
specify this option. Even if all checks pass, the tool may still encounter
problems if, for example, one of the L<"--alter"> statements uses
incorrect syntax.
=item --child-tables
type: array
@@ -6885,6 +6892,18 @@ type: Array
Read this comma-separated list of config files; if specified, this must be the
first option on the command line.
=item --critical-load
type: Array; default: Threads_running=50; group: Throttle
Examine SHOW GLOBAL STATUS after every chunk, and abort if any status variables
are higher than the threshold. The option accepts a comma-separated list of
MySQL status variables to check for a threshold. An optional C<=MAX_VALUE> (or
C<:MAX_VALUE>) can follow each variable. If not given, the tool determines a
threshold by examining the current value and doubling it.
See also L<"--max-load">.
=item --defaults-file
short form: -F; type: string
@@ -6903,7 +6922,7 @@ if there are no errors and the new table successfully takes it place.
=item --dry-run
Do not create triggers, copy rows, or L<"--swap-tables">.
Do not create triggers, copy rows, or L<"--[no]swap-tables">.
=item --execute
@@ -7069,16 +7088,6 @@ replication lag and checksum differences, insert the values C<h=10.10.1.16> and
C<h=10.10.1.17> into the table. Currently, the DSNs are ordered by id, but id
and parent_id are otherwise ignored.
=item --[no]swap-tables
default: yes
Swap the the original table and the new, altered table. This step
essentially completes the online schema change process by making the
temporary table with the new schema take the place of the original table.
The original tables becomes the "old table" and is dropped if
L<"--[no]drop-old-table"> is specified.
=item --retries
type: int; default: 3
@@ -7099,6 +7108,17 @@ short form: -S; type: string
Socket file to use for connection.
=item --[no]swap-tables
default: yes
Swap the the original table and the new, altered table. This step
essentially completes the online schema change process by making the
temporary table with the new schema take the place of the original table.
The original tables becomes the "old table" and is dropped if
L<"--[no]drop-old-table"> is specified.
=item --update-foreign-keys-method
type: string

View File

@@ -39,18 +39,31 @@ use constant PTDEBUG => $ENV{PTDEBUG} || 0;
# MySQLStatusWaiter object
sub new {
my ( $class, %args ) = @_;
my @required_args = qw(spec get_status sleep oktorun);
my @required_args = qw(max_spec get_status sleep oktorun);
foreach my $arg ( @required_args ) {
die "I need a $arg argument" unless defined $args{$arg};
}
my $max_val_for = _parse_spec(%args);
PTDEBUG && _d('Parsing spec for max thresholds');
my $max_val_for = _parse_spec(
spec => $args{max_spec},
get_status => $args{get_status},
threshold_factor => 0.2, # +20%
);
PTDEBUG && _d('Parsing spec for critical thresholds');
my $critical_val_for = _parse_spec(
spec => $args{critical_spec} || [],
get_status => $args{get_status},
threshold_factor => 1.0, # double (x2; +100%)
);
my $self = {
get_status => $args{get_status},
sleep => $args{sleep},
oktorun => $args{oktorun},
max_val_for => $max_val_for,
get_status => $args{get_status},
sleep => $args{sleep},
oktorun => $args{oktorun},
max_val_for => $max_val_for,
critical_val_for => $critical_val_for,
};
return bless $self, $class;
@@ -73,10 +86,8 @@ sub _parse_spec {
}
my ($spec, $get_status) = @args{@required_args};
if ( !@$spec ) {
PTDEBUG && _d('No spec, disabling status var waits');
return;
}
return unless $spec && scalar @$spec;
my $threshold_factor = $args{threshold_factor} || 0.20;
my %max_val_for;
foreach my $var_val ( @$spec ) {
@@ -85,7 +96,7 @@ sub _parse_spec {
if ( !$val ) {
my $init_val = $get_status->($var);
PTDEBUG && _d('Initial', $var, 'value:', $init_val);
$val = int(($init_val * .20) + $init_val);
$val = int(($init_val * $threshold_factor) + $init_val);
}
PTDEBUG && _d('Wait if', $var, '>=', $val);
$max_val_for{$var} = $val;
@@ -101,6 +112,11 @@ sub max_values {
return $self->{max_val_for};
}
sub critical_values {
my ($self) = @_;
return $self->{critical_val_for};
}
# Sub: wait
# Wait until all variables' values are less than their permitted maximums.
#
@@ -117,7 +133,7 @@ sub wait {
my $oktorun = $self->{oktorun};
my $get_status = $self->{get_status};
my $sleep = $self->{sleep};
my %vals_too_high = %{$self->{max_val_for}};
my $pr_callback;
if ( $pr ) {
@@ -144,6 +160,12 @@ sub wait {
foreach my $var ( sort keys %vals_too_high ) {
my $val = $get_status->($var);
PTDEBUG && _d($var, '=', $val);
if ( $val
&& exists $self->{critical_val_for}->{$var}
&& $val >= $self->{critical_val_for}->{$var} ) {
die "$var=$val exceeds its critical threshold "
. "$self->{critical_val_for}->{$var}\n";
}
if ( !$val || $val >= $self->{max_val_for}->{$var} ) {
$vals_too_high{$var} = $val;
}

View File

@@ -9,7 +9,7 @@ BEGIN {
use strict;
use warnings FATAL => 'all';
use English qw(-no_match_vars);
use Test::More tests => 12;
use Test::More tests => 14;
use MySQLStatusWaiter;
use PerconaTest;
@@ -72,7 +72,7 @@ my $sw = new MySQLStatusWaiter(
oktorun => \&oktorun,
get_status => \&get_status,
sleep => \&sleep,
spec => [qw(Threads_connected Threads_running)],
max_spec => [qw(Threads_connected Threads_running)],
);
is_deeply(
@@ -136,7 +136,7 @@ $sw = new MySQLStatusWaiter(
oktorun => \&oktorun,
get_status => \&get_status,
sleep => \&sleep,
spec => [qw(Threads_connected=5 Threads_running=5)],
max_spec => [qw(Threads_connected=5 Threads_running=5)],
);
is_deeply(
@@ -178,7 +178,7 @@ $sw = new MySQLStatusWaiter(
oktorun => \&oktorun,
get_status => \&get_status,
sleep => \&sleep,
spec => [],
max_spec => [],
);
is(
@@ -204,6 +204,40 @@ is(
"No spec, no sleep"
);
# ############################################################################
# Critical thresholds (with static vals).
# ############################################################################
@vals = (
# first check, no wait
{ Threads_running => 1, },
{ Threads_running => 9, },
);
$sw = new MySQLStatusWaiter(
oktorun => \&oktorun,
get_status => \&get_status,
sleep => \&sleep,
max_spec => [qw(Threads_running=4)],
critical_spec => [qw(Threads_running=8)],
);
@checked = ();
$slept = 0;
$sw->wait();
is(
$slept,
0,
"Vals not critical, did not sleep"
);
throws_ok(
sub { $sw->wait(); },
qr/Threads_running=9 exceeds its critical threshold 8/,
"Die on critical threshold"
);
# #############################################################################
# Done.
# #############################################################################