Merge pull request #50 from percona/lp-1491261-pt-osc-alter-before-rename

Add --[no]analyze-before-swap to pt-osc (LP 1491261)
This commit is contained in:
Daniel Nichter
2015-11-03 13:51:12 -08:00

View File

@@ -8171,6 +8171,38 @@ sub main {
# http://bugs.mysql.com/bug.php?id=45694
my $lock_in_share_mode = $server_version < '5.1' ? 0 : 1;
# ########################################################################
# Check if analyze-before-swap is necessary.
# https://bugs.launchpad.net/percona-toolkit/+bug/1491261
# ########################################################################
my $analyze_table = $o->get('analyze-before-swap');
if ( $o->got('analyze-before-swap') ) {
# User specified so respect their wish. If --analyze-before-swap, do it
# regardless of MySQL version and innodb_stats_peristent.
# If --no-analyze-before-swap, don't do it.
PTDEBUG && _d('User specified explicit --analyze-before-swap:',
($analyze_table ? 'on' : 'off'));
}
elsif ( $analyze_table ) {
# User did not specify --analyze-before-swap on command line, and it
# defaults to "yes", so auto-check for the conditions it's affected by
# and enable only if those conditions are true.
if ( $server_version >= '5.6' ) {
my (undef, $innodb_stats_persistent) = $cxn->dbh->selectrow_array(
"SHOW VARIABLES LIKE 'innodb_stats_persistent'");
if ($innodb_stats_persistent eq 'ON' || $innodb_stats_persistent eq '1') {
PTDEBUG && _d('innodb_stats_peristent is ON, enabling --analyze-before-swap');
$analyze_table = 1;
} else {
PTDEBUG && _d('innodb_stats_peristent is OFF, disabling --analyze-before-swap');
$analyze_table = 0;
}
} else {
PTDEBUG && _d('MySQL < 5.6, disabling --analyze-before-swap');
$analyze_table = 0;
}
}
# ########################################################################
# Create --plugin.
# ########################################################################
@@ -9401,15 +9433,16 @@ sub main {
if ( $o->get('swap-tables') ) {
eval {
$old_tbl = swap_tables(
orig_tbl => $orig_tbl,
new_tbl => $new_tbl,
suffix => '_old',
Cxn => $cxn,
Quoter => $q,
OptionParser => $o,
Retry => $retry,
tries => $tries,
stats => \%stats,
orig_tbl => $orig_tbl,
new_tbl => $new_tbl,
suffix => '_old',
Cxn => $cxn,
Quoter => $q,
OptionParser => $o,
Retry => $retry,
tries => $tries,
stats => \%stats,
analyze_table => $analyze_table,
);
};
if ( $EVAL_ERROR ) {
@@ -9461,13 +9494,14 @@ sub main {
}
elsif ( $alter_fk_method eq 'drop_swap' ) {
drop_swap(
orig_tbl => $orig_tbl,
new_tbl => $new_tbl,
Cxn => $cxn,
OptionParser => $o,
stats => \%stats,
Retry => $retry,
tries => $tries,
orig_tbl => $orig_tbl,
new_tbl => $new_tbl,
Cxn => $cxn,
OptionParser => $o,
stats => \%stats,
Retry => $retry,
tries => $tries,
analyze_table => $analyze_table,
);
}
elsif ( !$alter_fk_method
@@ -9573,6 +9607,7 @@ sub validate_tries {
copy_rows
swap_tables
update_foreign_keys
analyze_table
);
my %user_tries;
my $user_tries = $o->get('tries');
@@ -9950,8 +9985,24 @@ sub swap_tables {
return $orig_tbl;
}
elsif ( $o->get('execute') ) {
print ts("Swapping tables...\n");
# ANALYZE TABLE before renaming to update InnoDB optimizer statistics.
# https://bugs.launchpad.net/percona-toolkit/+bug/1491261
if ( $args{analyze_table} ) {
print ts("Analyzing new table...\n");
my $sql_analyze = "ANALYZE TABLE $new_tbl->{name} /* pt-online-schema-change */";
osc_retry(
Cxn => $cxn,
Retry => $retry,
tries => $tries->{analyze_table},
stats => $stats,
code => sub {
PTDEBUG && _d($sql_analyze);
$cxn->dbh()->do($sql_analyze);
},
);
}
print ts("Swapping tables...\n");
while ( $name_tries-- ) {
$table_name = $prefix . $table_name;
@@ -9961,6 +10012,7 @@ sub swap_tables {
$truncated_table_name);
$table_name = $truncated_table_name;
}
my $sql = "RENAME TABLE $orig_tbl->{name} "
. "TO " . $q->quote($orig_tbl->{db}, $table_name)
. ", $new_tbl->{name} TO $orig_tbl->{name}";
@@ -10286,6 +10338,23 @@ sub drop_swap {
print ts("Drop-swapping tables...\n");
}
# ANALYZE TABLE before renaming to update InnoDB optimizer statistics.
# https://bugs.launchpad.net/percona-toolkit/+bug/1491261
if ( $args{analyze_table} ) {
print ts("Analyzing new table...\n");
my $sql_analyze = "ANALYZE TABLE $new_tbl->{name} /* pt-online-schema-change */";
osc_retry(
Cxn => $cxn,
Retry => $retry,
tries => $tries->{analyze_table},
stats => $stats,
code => sub {
PTDEBUG && _d($sql_analyze);
$cxn->dbh()->do($sql_analyze);
},
);
}
my @sqls = (
"SET foreign_key_checks=0",
"DROP TABLE IF EXISTS $orig_tbl->{name}",
@@ -10497,6 +10566,7 @@ sub osc_retry {
foreach my $arg ( @required_args ) {
die "I need a $arg argument" unless $args{$arg};
}
my $cxn = $args{Cxn};
my $retry = $args{Retry};
my $tries = $args{tries};
@@ -11053,6 +11123,22 @@ tool's built-in functionality if desired.
=back
=item --[no]analyze-before-swap
default: yes
Execute ANALYZE TABLE on the new table before swaping with the old one.
By default, this happens only when running MySQL 5.6 and newer, and
C<innodb_stats_persistent> is enabled. Specify the option explicitly to enable
or disable it regardless of MySQL version and C<innodb_stats_persistent>.
This circumvents a potentially serious issue related to InnoDB optimizer
statistics. If the table being alerted is busy and the tool completes quickly,
the new table will not have optimizer statistics after being swapped. This can
cause fast, index-using queries to do full table scans until optimizer
statistics are updated (usually after 10 seconds). If the table is large and
the server very busy, this can cause an outage.
=item --ask-pass
Prompt for a password when connecting to MySQL.
@@ -11592,6 +11678,7 @@ MAGIC_tries
copy_rows 10 0.25
swap_tables 10 1
update_foreign_keys 10 1
analyze_table 10 1
To change the defaults, specify the new values like: