mirror of
https://github.com/percona/percona-toolkit.git
synced 2025-09-27 16:12:04 +00:00
Merge release-2.2.4.
This commit is contained in:
17
Changelog
17
Changelog
@@ -1,5 +1,22 @@
|
||||
Changelog for Percona Toolkit
|
||||
|
||||
* Implemented pt-query-digest anonymous JSON output
|
||||
* Implemented pt-online-schema-change timestamp output
|
||||
* Fixed bug 1182856: Zero values causes "Invalid --set-vars value: var=0"
|
||||
* Fixed bug 1195034: pt-deadlock-logger error: Use of uninitialized value $ts in pattern match (m//)
|
||||
* Fixed bug 1137556: pt-heartbeat docs don't account for --utc
|
||||
* Fixed bug 1188264: pt-online-schema-change error copying rows: Undefined subroutine &pt_online_schema_change::get
|
||||
* Fixed bug 1171968: pt-query-digest docs don't mention --type=rawlog
|
||||
* Fixed bug 1176010: pt-query-digest doesn't group db and `db` together
|
||||
* Fixed bug 1174956: pt-query-digest and pt-fingerprint don't strip some multi-line comments
|
||||
* Fixed bug 1172317: pt-sift does not work if pt-stalk did not collect due to a full disk
|
||||
* Fixed bug 1136559: pt-table-checksum: Deep recursion on subroutine "SchemaIterator::_iterate_dbh"
|
||||
* Fixed bug 1199591: pt-table-checksum doesn't use non-unique index with highest cardinality
|
||||
* Fixed bug 1163735: pt-table-checksum fails if explicit_defaults_for_timestamp is enabled in 5.6
|
||||
* Fixed bug 1168434: pt-upgrade reports differences on NULL
|
||||
* Fixed bug 1168106: pt-variable-advisor has the wrong default value for innodb_max_dirty_pages_pct in 5.5 and 5.6
|
||||
* Fixed bug 1168110: pt-variable-advisor shows key_buffer_size in 5.6 as unconfigured (even though it is)
|
||||
|
||||
v2.2.3 released 2013-06-17
|
||||
|
||||
* Added new tool: pt-agent
|
||||
|
@@ -52,7 +52,7 @@ BEGIN {
|
||||
{
|
||||
package Percona::Toolkit;
|
||||
|
||||
our $VERSION = '2.2.3';
|
||||
our $VERSION = '2.2.4';
|
||||
|
||||
use strict;
|
||||
use warnings FATAL => 'all';
|
||||
@@ -3560,7 +3560,7 @@ sub set_vars {
|
||||
if ( $user_vars ) {
|
||||
foreach my $var_val ( @$user_vars ) {
|
||||
my ($var, $val) = $var_val =~ m/([^\s=]+)=(\S+)/;
|
||||
die "Invalid --set-vars value: $var_val\n" unless $var && $val;
|
||||
die "Invalid --set-vars value: $var_val\n" unless $var && defined $val;
|
||||
$user_vars{$var} = {
|
||||
val => $val,
|
||||
default => 0,
|
||||
@@ -3574,7 +3574,7 @@ sub set_vars {
|
||||
%default_vars = map {
|
||||
my $var_val = $_;
|
||||
my ($var, $val) = $var_val =~ m/([^\s=]+)=(\S+)/;
|
||||
die "Invalid --set-vars value: $var_val\n" unless $var && $val;
|
||||
die "Invalid --set-vars value: $var_val\n" unless $var && defined $val;
|
||||
$var => {
|
||||
val => $val,
|
||||
default => 1,
|
||||
|
@@ -1028,7 +1028,7 @@ sub set_vars {
|
||||
if ( $user_vars ) {
|
||||
foreach my $var_val ( @$user_vars ) {
|
||||
my ($var, $val) = $var_val =~ m/([^\s=]+)=(\S+)/;
|
||||
die "Invalid --set-vars value: $var_val\n" unless $var && $val;
|
||||
die "Invalid --set-vars value: $var_val\n" unless $var && defined $val;
|
||||
$user_vars{$var} = {
|
||||
val => $val,
|
||||
default => 0,
|
||||
@@ -1042,7 +1042,7 @@ sub set_vars {
|
||||
%default_vars = map {
|
||||
my $var_val = $_;
|
||||
my ($var, $val) = $var_val =~ m/([^\s=]+)=(\S+)/;
|
||||
die "Invalid --set-vars value: $var_val\n" unless $var && $val;
|
||||
die "Invalid --set-vars value: $var_val\n" unless $var && defined $val;
|
||||
$var => {
|
||||
val => $val,
|
||||
default => 1,
|
||||
|
@@ -43,7 +43,7 @@ BEGIN {
|
||||
{
|
||||
package Percona::Toolkit;
|
||||
|
||||
our $VERSION = '2.2.3';
|
||||
our $VERSION = '2.2.4';
|
||||
|
||||
use strict;
|
||||
use warnings FATAL => 'all';
|
||||
@@ -1755,7 +1755,7 @@ sub set_vars {
|
||||
if ( $user_vars ) {
|
||||
foreach my $var_val ( @$user_vars ) {
|
||||
my ($var, $val) = $var_val =~ m/([^\s=]+)=(\S+)/;
|
||||
die "Invalid --set-vars value: $var_val\n" unless $var && $val;
|
||||
die "Invalid --set-vars value: $var_val\n" unless $var && defined $val;
|
||||
$user_vars{$var} = {
|
||||
val => $val,
|
||||
default => 0,
|
||||
@@ -1769,7 +1769,7 @@ sub set_vars {
|
||||
%default_vars = map {
|
||||
my $var_val = $_;
|
||||
my ($var, $val) = $var_val =~ m/([^\s=]+)=(\S+)/;
|
||||
die "Invalid --set-vars value: $var_val\n" unless $var && $val;
|
||||
die "Invalid --set-vars value: $var_val\n" unless $var && defined $val;
|
||||
$var => {
|
||||
val => $val,
|
||||
default => 1,
|
||||
|
@@ -43,7 +43,7 @@ BEGIN {
|
||||
{
|
||||
package Percona::Toolkit;
|
||||
|
||||
our $VERSION = '2.2.3';
|
||||
our $VERSION = '2.2.4';
|
||||
|
||||
use strict;
|
||||
use warnings FATAL => 'all';
|
||||
@@ -1755,7 +1755,7 @@ sub set_vars {
|
||||
if ( $user_vars ) {
|
||||
foreach my $var_val ( @$user_vars ) {
|
||||
my ($var, $val) = $var_val =~ m/([^\s=]+)=(\S+)/;
|
||||
die "Invalid --set-vars value: $var_val\n" unless $var && $val;
|
||||
die "Invalid --set-vars value: $var_val\n" unless $var && defined $val;
|
||||
$user_vars{$var} = {
|
||||
val => $val,
|
||||
default => 0,
|
||||
@@ -1769,7 +1769,7 @@ sub set_vars {
|
||||
%default_vars = map {
|
||||
my $var_val = $_;
|
||||
my ($var, $val) = $var_val =~ m/([^\s=]+)=(\S+)/;
|
||||
die "Invalid --set-vars value: $var_val\n" unless $var && $val;
|
||||
die "Invalid --set-vars value: $var_val\n" unless $var && defined $val;
|
||||
$var => {
|
||||
val => $val,
|
||||
default => 1,
|
||||
|
@@ -42,7 +42,7 @@ BEGIN {
|
||||
{
|
||||
package Percona::Toolkit;
|
||||
|
||||
our $VERSION = '2.2.3';
|
||||
our $VERSION = '2.2.4';
|
||||
|
||||
use strict;
|
||||
use warnings FATAL => 'all';
|
||||
@@ -1105,7 +1105,7 @@ sub set_vars {
|
||||
if ( $user_vars ) {
|
||||
foreach my $var_val ( @$user_vars ) {
|
||||
my ($var, $val) = $var_val =~ m/([^\s=]+)=(\S+)/;
|
||||
die "Invalid --set-vars value: $var_val\n" unless $var && $val;
|
||||
die "Invalid --set-vars value: $var_val\n" unless $var && defined $val;
|
||||
$user_vars{$var} = {
|
||||
val => $val,
|
||||
default => 0,
|
||||
@@ -1119,7 +1119,7 @@ sub set_vars {
|
||||
%default_vars = map {
|
||||
my $var_val = $_;
|
||||
my ($var, $val) = $var_val =~ m/([^\s=]+)=(\S+)/;
|
||||
die "Invalid --set-vars value: $var_val\n" unless $var && $val;
|
||||
die "Invalid --set-vars value: $var_val\n" unless $var && defined $val;
|
||||
$var => {
|
||||
val => $val,
|
||||
default => 1,
|
||||
@@ -4804,6 +4804,11 @@ sub parse_deadlocks {
|
||||
|
||||
# Extract some miscellaneous data from the deadlock.
|
||||
my ( $ts ) = $dl_text =~ m/^$s$/m;
|
||||
if ( !$ts ) {
|
||||
# https://bugs.launchpad.net/percona-toolkit/+bug/1195034
|
||||
# 130624 17:39:24TOO DEEP OR LONG SEARCH IN THE LOCK TABLE ...
|
||||
($ts) = $dl_text =~ m/^${s}TOO DEEP/m;
|
||||
}
|
||||
my ( $year, $mon, $day, $hour, $min, $sec ) = $ts =~ m/^((?:\d\d)?\d\d)-?(\d\d)-?(\d\d) +(\d+):(\d+):(\d+)$/;
|
||||
if ( length($year) == 2 ) {
|
||||
$year += 2000;
|
||||
|
@@ -38,7 +38,7 @@ BEGIN {
|
||||
{
|
||||
package Percona::Toolkit;
|
||||
|
||||
our $VERSION = '2.2.3';
|
||||
our $VERSION = '2.2.4';
|
||||
|
||||
use strict;
|
||||
use warnings FATAL => 'all';
|
||||
@@ -1101,7 +1101,7 @@ sub set_vars {
|
||||
if ( $user_vars ) {
|
||||
foreach my $var_val ( @$user_vars ) {
|
||||
my ($var, $val) = $var_val =~ m/([^\s=]+)=(\S+)/;
|
||||
die "Invalid --set-vars value: $var_val\n" unless $var && $val;
|
||||
die "Invalid --set-vars value: $var_val\n" unless $var && defined $val;
|
||||
$user_vars{$var} = {
|
||||
val => $val,
|
||||
default => 0,
|
||||
@@ -1115,7 +1115,7 @@ sub set_vars {
|
||||
%default_vars = map {
|
||||
my $var_val = $_;
|
||||
my ($var, $val) = $var_val =~ m/([^\s=]+)=(\S+)/;
|
||||
die "Invalid --set-vars value: $var_val\n" unless $var && $val;
|
||||
die "Invalid --set-vars value: $var_val\n" unless $var && defined $val;
|
||||
$var => {
|
||||
val => $val,
|
||||
default => 1,
|
||||
|
@@ -39,7 +39,7 @@ BEGIN {
|
||||
{
|
||||
package Percona::Toolkit;
|
||||
|
||||
our $VERSION = '2.2.3';
|
||||
our $VERSION = '2.2.4';
|
||||
|
||||
use strict;
|
||||
use warnings FATAL => 'all';
|
||||
@@ -2087,7 +2087,7 @@ sub set_vars {
|
||||
if ( $user_vars ) {
|
||||
foreach my $var_val ( @$user_vars ) {
|
||||
my ($var, $val) = $var_val =~ m/([^\s=]+)=(\S+)/;
|
||||
die "Invalid --set-vars value: $var_val\n" unless $var && $val;
|
||||
die "Invalid --set-vars value: $var_val\n" unless $var && defined $val;
|
||||
$user_vars{$var} = {
|
||||
val => $val,
|
||||
default => 0,
|
||||
@@ -2101,7 +2101,7 @@ sub set_vars {
|
||||
%default_vars = map {
|
||||
my $var_val = $_;
|
||||
my ($var, $val) = $var_val =~ m/([^\s=]+)=(\S+)/;
|
||||
die "Invalid --set-vars value: $var_val\n" unless $var && $val;
|
||||
die "Invalid --set-vars value: $var_val\n" unless $var && defined $val;
|
||||
$var => {
|
||||
val => $val,
|
||||
default => 1,
|
||||
@@ -3297,58 +3297,63 @@ sub _iterate_dbh {
|
||||
$self->{dbs} = \@dbs;
|
||||
}
|
||||
|
||||
if ( !$self->{db} ) {
|
||||
$self->{db} = shift @{$self->{dbs}};
|
||||
PTDEBUG && _d('Next database:', $self->{db});
|
||||
return unless $self->{db};
|
||||
}
|
||||
|
||||
if ( !defined $self->{tbls} ) {
|
||||
my $sql = 'SHOW /*!50002 FULL*/ TABLES FROM ' . $q->quote($self->{db});
|
||||
PTDEBUG && _d($sql);
|
||||
my @tbls = map {
|
||||
$_->[0]; # (tbl, type)
|
||||
DATABASE:
|
||||
while ( $self->{db} || defined(my $db = shift @{$self->{dbs}}) ) {
|
||||
if ( !$self->{db} ) {
|
||||
PTDEBUG && _d('Next database:', $db);
|
||||
$self->{db} = $db;
|
||||
}
|
||||
grep {
|
||||
my ($tbl, $type) = @$_;
|
||||
(!$type || ($type ne 'VIEW'))
|
||||
&& $self->_resume_from_table($tbl)
|
||||
&& $self->table_is_allowed($self->{db}, $tbl);
|
||||
}
|
||||
@{$dbh->selectall_arrayref($sql)};
|
||||
PTDEBUG && _d('Found', scalar @tbls, 'tables in database', $self->{db});
|
||||
$self->{tbls} = \@tbls;
|
||||
}
|
||||
|
||||
while ( my $tbl = shift @{$self->{tbls}} ) {
|
||||
my $ddl = eval { $tp->get_create_table($dbh, $self->{db}, $tbl) };
|
||||
if ( my $e = $EVAL_ERROR ) {
|
||||
my $table_name = "$self->{db}.$tbl";
|
||||
if ( $e =~ /\QTable '$table_name' doesn't exist/ ) {
|
||||
PTDEBUG && _d("Skipping $table_name because it no longer exists");
|
||||
if ( !$self->{tbls} ) {
|
||||
my $sql = 'SHOW /*!50002 FULL*/ TABLES FROM ' . $q->quote($self->{db});
|
||||
PTDEBUG && _d($sql);
|
||||
my @tbls = map {
|
||||
$_->[0]; # (tbl, type)
|
||||
}
|
||||
else {
|
||||
warn "Skipping $table_name because SHOW CREATE TABLE failed: $e";
|
||||
grep {
|
||||
my ($tbl, $type) = @$_;
|
||||
(!$type || ($type ne 'VIEW'))
|
||||
&& $self->_resume_from_table($tbl)
|
||||
&& $self->table_is_allowed($self->{db}, $tbl);
|
||||
}
|
||||
next;
|
||||
@{$dbh->selectall_arrayref($sql)};
|
||||
PTDEBUG && _d('Found', scalar @tbls, 'tables in database',$self->{db});
|
||||
$self->{tbls} = \@tbls;
|
||||
}
|
||||
my $tbl_struct = $tp->parse($ddl);
|
||||
if ( $self->engine_is_allowed($tbl_struct->{engine}) ) {
|
||||
return {
|
||||
db => $self->{db},
|
||||
tbl => $tbl,
|
||||
name => $q->quote($self->{db}, $tbl),
|
||||
ddl => $ddl,
|
||||
tbl_struct => $tbl_struct,
|
||||
};
|
||||
|
||||
TABLE:
|
||||
while ( my $tbl = shift @{$self->{tbls}} ) {
|
||||
my $ddl = eval { $tp->get_create_table($dbh, $self->{db}, $tbl) };
|
||||
if ( my $e = $EVAL_ERROR ) {
|
||||
my $table_name = "$self->{db}.$tbl";
|
||||
if ( $e =~ /\QTable '$table_name' doesn't exist/ ) {
|
||||
PTDEBUG && _d("$table_name no longer exists");
|
||||
}
|
||||
else {
|
||||
warn "Skipping $table_name because SHOW CREATE TABLE failed: $e";
|
||||
}
|
||||
next TABLE;
|
||||
}
|
||||
|
||||
my $tbl_struct = $tp->parse($ddl);
|
||||
if ( $self->engine_is_allowed($tbl_struct->{engine}) ) {
|
||||
return {
|
||||
db => $self->{db},
|
||||
tbl => $tbl,
|
||||
name => $q->quote($self->{db}, $tbl),
|
||||
ddl => $ddl,
|
||||
tbl_struct => $tbl_struct,
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
PTDEBUG && _d('No more tables in database', $self->{db});
|
||||
$self->{db} = undef;
|
||||
$self->{tbls} = undef;
|
||||
PTDEBUG && _d('No more tables in database', $self->{db});
|
||||
$self->{db} = undef;
|
||||
$self->{tbls} = undef;
|
||||
} # DATABASE
|
||||
|
||||
return $self->_iterate_dbh();
|
||||
PTDEBUG && _d('No more databases');
|
||||
return;
|
||||
}
|
||||
|
||||
sub database_is_allowed {
|
||||
|
@@ -1029,7 +1029,7 @@ sub set_vars {
|
||||
if ( $user_vars ) {
|
||||
foreach my $var_val ( @$user_vars ) {
|
||||
my ($var, $val) = $var_val =~ m/([^\s=]+)=(\S+)/;
|
||||
die "Invalid --set-vars value: $var_val\n" unless $var && $val;
|
||||
die "Invalid --set-vars value: $var_val\n" unless $var && defined $val;
|
||||
$user_vars{$var} = {
|
||||
val => $val,
|
||||
default => 0,
|
||||
@@ -1043,7 +1043,7 @@ sub set_vars {
|
||||
%default_vars = map {
|
||||
my $var_val = $_;
|
||||
my ($var, $val) = $var_val =~ m/([^\s=]+)=(\S+)/;
|
||||
die "Invalid --set-vars value: $var_val\n" unless $var && $val;
|
||||
die "Invalid --set-vars value: $var_val\n" unless $var && defined $val;
|
||||
$var => {
|
||||
val => $val,
|
||||
default => 1,
|
||||
|
@@ -35,7 +35,7 @@ BEGIN {
|
||||
{
|
||||
package Percona::Toolkit;
|
||||
|
||||
our $VERSION = '2.2.3';
|
||||
our $VERSION = '2.2.4';
|
||||
|
||||
use strict;
|
||||
use warnings FATAL => 'all';
|
||||
@@ -1521,7 +1521,7 @@ sub set_vars {
|
||||
if ( $user_vars ) {
|
||||
foreach my $var_val ( @$user_vars ) {
|
||||
my ($var, $val) = $var_val =~ m/([^\s=]+)=(\S+)/;
|
||||
die "Invalid --set-vars value: $var_val\n" unless $var && $val;
|
||||
die "Invalid --set-vars value: $var_val\n" unless $var && defined $val;
|
||||
$user_vars{$var} = {
|
||||
val => $val,
|
||||
default => 0,
|
||||
@@ -1535,7 +1535,7 @@ sub set_vars {
|
||||
%default_vars = map {
|
||||
my $var_val = $_;
|
||||
my ($var, $val) = $var_val =~ m/([^\s=]+)=(\S+)/;
|
||||
die "Invalid --set-vars value: $var_val\n" unless $var && $val;
|
||||
die "Invalid --set-vars value: $var_val\n" unless $var && defined $val;
|
||||
$var => {
|
||||
val => $val,
|
||||
default => 1,
|
||||
|
@@ -1030,7 +1030,7 @@ sub set_vars {
|
||||
if ( $user_vars ) {
|
||||
foreach my $var_val ( @$user_vars ) {
|
||||
my ($var, $val) = $var_val =~ m/([^\s=]+)=(\S+)/;
|
||||
die "Invalid --set-vars value: $var_val\n" unless $var && $val;
|
||||
die "Invalid --set-vars value: $var_val\n" unless $var && defined $val;
|
||||
$user_vars{$var} = {
|
||||
val => $val,
|
||||
default => 0,
|
||||
@@ -1044,7 +1044,7 @@ sub set_vars {
|
||||
%default_vars = map {
|
||||
my $var_val = $_;
|
||||
my ($var, $val) = $var_val =~ m/([^\s=]+)=(\S+)/;
|
||||
die "Invalid --set-vars value: $var_val\n" unless $var && $val;
|
||||
die "Invalid --set-vars value: $var_val\n" unless $var && defined $val;
|
||||
$var => {
|
||||
val => $val,
|
||||
default => 1,
|
||||
@@ -1532,8 +1532,8 @@ sub new {
|
||||
sub strip_comments {
|
||||
my ( $self, $query ) = @_;
|
||||
return unless $query;
|
||||
$query =~ s/$olc_re//go;
|
||||
$query =~ s/$mlc_re//go;
|
||||
$query =~ s/$olc_re//go;
|
||||
if ( $query =~ m/$vlc_rf/i ) { # contains show + version
|
||||
$query =~ s/$vlc_re//go;
|
||||
}
|
||||
@@ -1600,9 +1600,9 @@ sub fingerprint {
|
||||
if ( my ($beginning) = $query =~ m/\A((?:INSERT|REPLACE)(?: IGNORE)?\s+INTO.+?VALUES\s*\(.*?\))\s*,\s*\(/is ) {
|
||||
$query = $beginning; # Shorten multi-value INSERT statements ASAP
|
||||
}
|
||||
|
||||
$query =~ s/$olc_re//go;
|
||||
|
||||
$query =~ s/$mlc_re//go;
|
||||
$query =~ s/$olc_re//go;
|
||||
$query =~ s/\Ause \S+\Z/use ?/i # Abstract the DB in USE
|
||||
&& return $query;
|
||||
|
||||
|
@@ -37,7 +37,7 @@ BEGIN {
|
||||
{
|
||||
package Percona::Toolkit;
|
||||
|
||||
our $VERSION = '2.2.3';
|
||||
our $VERSION = '2.2.4';
|
||||
|
||||
use strict;
|
||||
use warnings FATAL => 'all';
|
||||
@@ -1100,7 +1100,7 @@ sub set_vars {
|
||||
if ( $user_vars ) {
|
||||
foreach my $var_val ( @$user_vars ) {
|
||||
my ($var, $val) = $var_val =~ m/([^\s=]+)=(\S+)/;
|
||||
die "Invalid --set-vars value: $var_val\n" unless $var && $val;
|
||||
die "Invalid --set-vars value: $var_val\n" unless $var && defined $val;
|
||||
$user_vars{$var} = {
|
||||
val => $val,
|
||||
default => 0,
|
||||
@@ -1114,7 +1114,7 @@ sub set_vars {
|
||||
%default_vars = map {
|
||||
my $var_val = $_;
|
||||
my ($var, $val) = $var_val =~ m/([^\s=]+)=(\S+)/;
|
||||
die "Invalid --set-vars value: $var_val\n" unless $var && $val;
|
||||
die "Invalid --set-vars value: $var_val\n" unless $var && defined $val;
|
||||
$var => {
|
||||
val => $val,
|
||||
default => 1,
|
||||
|
@@ -38,7 +38,7 @@ BEGIN {
|
||||
{
|
||||
package Percona::Toolkit;
|
||||
|
||||
our $VERSION = '2.2.3';
|
||||
our $VERSION = '2.2.4';
|
||||
|
||||
use strict;
|
||||
use warnings FATAL => 'all';
|
||||
@@ -1837,7 +1837,7 @@ sub set_vars {
|
||||
if ( $user_vars ) {
|
||||
foreach my $var_val ( @$user_vars ) {
|
||||
my ($var, $val) = $var_val =~ m/([^\s=]+)=(\S+)/;
|
||||
die "Invalid --set-vars value: $var_val\n" unless $var && $val;
|
||||
die "Invalid --set-vars value: $var_val\n" unless $var && defined $val;
|
||||
$user_vars{$var} = {
|
||||
val => $val,
|
||||
default => 0,
|
||||
@@ -1851,7 +1851,7 @@ sub set_vars {
|
||||
%default_vars = map {
|
||||
my $var_val = $_;
|
||||
my ($var, $val) = $var_val =~ m/([^\s=]+)=(\S+)/;
|
||||
die "Invalid --set-vars value: $var_val\n" unless $var && $val;
|
||||
die "Invalid --set-vars value: $var_val\n" unless $var && defined $val;
|
||||
$var => {
|
||||
val => $val,
|
||||
default => 1,
|
||||
@@ -5688,6 +5688,10 @@ be created with the following MAGIC_create_heartbeat table definition:
|
||||
The heartbeat table requires at least one row. If you manually create the
|
||||
heartbeat table, then you must insert a row by doing:
|
||||
|
||||
INSERT INTO heartbeat (ts, server_id) VALUES (NOW(), N);
|
||||
|
||||
or if using L<"--utc">:
|
||||
|
||||
INSERT INTO heartbeat (ts, server_id) VALUES (UTC_TIMESTAMP(), N);
|
||||
|
||||
where C<N> is the server's ID; do not use @@server_id because it will replicate
|
||||
@@ -5706,6 +5710,10 @@ Legacy tables do not support L<"--update"> instances on each slave
|
||||
of a multi-slave hierarchy like "master -> slave1 -> slave2".
|
||||
To manually insert the one required row into a legacy table:
|
||||
|
||||
INSERT INTO heartbeat (id, ts) VALUES (1, NOW());
|
||||
|
||||
or if using L<"--utc">:
|
||||
|
||||
INSERT INTO heartbeat (id, ts) VALUES (1, UTC_TIMESTAMP());
|
||||
|
||||
The tool automatically detects if the heartbeat table is legacy.
|
||||
@@ -6003,9 +6011,14 @@ Ignore system time zones and use only UTC. By default pt-heartbeat does
|
||||
not check or adjust for different system or MySQL time zones which can
|
||||
cause the tool to compute the lag incorrectly. Specifying this option is
|
||||
a good idea because it ensures that the tool works correctly regardless of
|
||||
time zones, but it also makes the tool backwards-incompatible with
|
||||
pt-heartbeat 2.2.3 and older (unless the older version of pt-heartbeat
|
||||
is running on a system that uses UTC).
|
||||
time zones.
|
||||
|
||||
If used, this option must be used for all pt-heartbeat instances:
|
||||
L<"--update">, L<"--monitor">, L<"--check">, etc. You should probably
|
||||
set the option in a L<"--config"> file. Mixing this option with pt-heartbeat
|
||||
instances not using this option will cause false-positive lag readings
|
||||
due to different time zones (unless all your systems are set to use UTC,
|
||||
in which case this option isn't required).
|
||||
|
||||
=item --version
|
||||
|
||||
|
@@ -45,7 +45,7 @@ BEGIN {
|
||||
{
|
||||
package Percona::Toolkit;
|
||||
|
||||
our $VERSION = '2.2.3';
|
||||
our $VERSION = '2.2.4';
|
||||
|
||||
use strict;
|
||||
use warnings FATAL => 'all';
|
||||
@@ -1682,7 +1682,7 @@ sub set_vars {
|
||||
if ( $user_vars ) {
|
||||
foreach my $var_val ( @$user_vars ) {
|
||||
my ($var, $val) = $var_val =~ m/([^\s=]+)=(\S+)/;
|
||||
die "Invalid --set-vars value: $var_val\n" unless $var && $val;
|
||||
die "Invalid --set-vars value: $var_val\n" unless $var && defined $val;
|
||||
$user_vars{$var} = {
|
||||
val => $val,
|
||||
default => 0,
|
||||
@@ -1696,7 +1696,7 @@ sub set_vars {
|
||||
%default_vars = map {
|
||||
my $var_val = $_;
|
||||
my ($var, $val) = $var_val =~ m/([^\s=]+)=(\S+)/;
|
||||
die "Invalid --set-vars value: $var_val\n" unless $var && $val;
|
||||
die "Invalid --set-vars value: $var_val\n" unless $var && defined $val;
|
||||
$var => {
|
||||
val => $val,
|
||||
default => 1,
|
||||
@@ -2377,8 +2377,8 @@ sub new {
|
||||
sub strip_comments {
|
||||
my ( $self, $query ) = @_;
|
||||
return unless $query;
|
||||
$query =~ s/$olc_re//go;
|
||||
$query =~ s/$mlc_re//go;
|
||||
$query =~ s/$olc_re//go;
|
||||
if ( $query =~ m/$vlc_rf/i ) { # contains show + version
|
||||
$query =~ s/$vlc_re//go;
|
||||
}
|
||||
@@ -2445,9 +2445,9 @@ sub fingerprint {
|
||||
if ( my ($beginning) = $query =~ m/\A((?:INSERT|REPLACE)(?: IGNORE)?\s+INTO.+?VALUES\s*\(.*?\))\s*,\s*\(/is ) {
|
||||
$query = $beginning; # Shorten multi-value INSERT statements ASAP
|
||||
}
|
||||
|
||||
$query =~ s/$olc_re//go;
|
||||
|
||||
$query =~ s/$mlc_re//go;
|
||||
$query =~ s/$olc_re//go;
|
||||
$query =~ s/\Ause \S+\Z/use ?/i # Abstract the DB in USE
|
||||
&& return $query;
|
||||
|
||||
@@ -4131,58 +4131,63 @@ sub _iterate_dbh {
|
||||
$self->{dbs} = \@dbs;
|
||||
}
|
||||
|
||||
if ( !$self->{db} ) {
|
||||
$self->{db} = shift @{$self->{dbs}};
|
||||
PTDEBUG && _d('Next database:', $self->{db});
|
||||
return unless $self->{db};
|
||||
}
|
||||
|
||||
if ( !defined $self->{tbls} ) {
|
||||
my $sql = 'SHOW /*!50002 FULL*/ TABLES FROM ' . $q->quote($self->{db});
|
||||
PTDEBUG && _d($sql);
|
||||
my @tbls = map {
|
||||
$_->[0]; # (tbl, type)
|
||||
DATABASE:
|
||||
while ( $self->{db} || defined(my $db = shift @{$self->{dbs}}) ) {
|
||||
if ( !$self->{db} ) {
|
||||
PTDEBUG && _d('Next database:', $db);
|
||||
$self->{db} = $db;
|
||||
}
|
||||
grep {
|
||||
my ($tbl, $type) = @$_;
|
||||
(!$type || ($type ne 'VIEW'))
|
||||
&& $self->_resume_from_table($tbl)
|
||||
&& $self->table_is_allowed($self->{db}, $tbl);
|
||||
}
|
||||
@{$dbh->selectall_arrayref($sql)};
|
||||
PTDEBUG && _d('Found', scalar @tbls, 'tables in database', $self->{db});
|
||||
$self->{tbls} = \@tbls;
|
||||
}
|
||||
|
||||
while ( my $tbl = shift @{$self->{tbls}} ) {
|
||||
my $ddl = eval { $tp->get_create_table($dbh, $self->{db}, $tbl) };
|
||||
if ( my $e = $EVAL_ERROR ) {
|
||||
my $table_name = "$self->{db}.$tbl";
|
||||
if ( $e =~ /\QTable '$table_name' doesn't exist/ ) {
|
||||
PTDEBUG && _d("Skipping $table_name because it no longer exists");
|
||||
if ( !$self->{tbls} ) {
|
||||
my $sql = 'SHOW /*!50002 FULL*/ TABLES FROM ' . $q->quote($self->{db});
|
||||
PTDEBUG && _d($sql);
|
||||
my @tbls = map {
|
||||
$_->[0]; # (tbl, type)
|
||||
}
|
||||
else {
|
||||
warn "Skipping $table_name because SHOW CREATE TABLE failed: $e";
|
||||
grep {
|
||||
my ($tbl, $type) = @$_;
|
||||
(!$type || ($type ne 'VIEW'))
|
||||
&& $self->_resume_from_table($tbl)
|
||||
&& $self->table_is_allowed($self->{db}, $tbl);
|
||||
}
|
||||
next;
|
||||
@{$dbh->selectall_arrayref($sql)};
|
||||
PTDEBUG && _d('Found', scalar @tbls, 'tables in database',$self->{db});
|
||||
$self->{tbls} = \@tbls;
|
||||
}
|
||||
my $tbl_struct = $tp->parse($ddl);
|
||||
if ( $self->engine_is_allowed($tbl_struct->{engine}) ) {
|
||||
return {
|
||||
db => $self->{db},
|
||||
tbl => $tbl,
|
||||
name => $q->quote($self->{db}, $tbl),
|
||||
ddl => $ddl,
|
||||
tbl_struct => $tbl_struct,
|
||||
};
|
||||
|
||||
TABLE:
|
||||
while ( my $tbl = shift @{$self->{tbls}} ) {
|
||||
my $ddl = eval { $tp->get_create_table($dbh, $self->{db}, $tbl) };
|
||||
if ( my $e = $EVAL_ERROR ) {
|
||||
my $table_name = "$self->{db}.$tbl";
|
||||
if ( $e =~ /\QTable '$table_name' doesn't exist/ ) {
|
||||
PTDEBUG && _d("$table_name no longer exists");
|
||||
}
|
||||
else {
|
||||
warn "Skipping $table_name because SHOW CREATE TABLE failed: $e";
|
||||
}
|
||||
next TABLE;
|
||||
}
|
||||
|
||||
my $tbl_struct = $tp->parse($ddl);
|
||||
if ( $self->engine_is_allowed($tbl_struct->{engine}) ) {
|
||||
return {
|
||||
db => $self->{db},
|
||||
tbl => $tbl,
|
||||
name => $q->quote($self->{db}, $tbl),
|
||||
ddl => $ddl,
|
||||
tbl_struct => $tbl_struct,
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
PTDEBUG && _d('No more tables in database', $self->{db});
|
||||
$self->{db} = undef;
|
||||
$self->{tbls} = undef;
|
||||
PTDEBUG && _d('No more tables in database', $self->{db});
|
||||
$self->{db} = undef;
|
||||
$self->{tbls} = undef;
|
||||
} # DATABASE
|
||||
|
||||
return $self->_iterate_dbh();
|
||||
PTDEBUG && _d('No more databases');
|
||||
return;
|
||||
}
|
||||
|
||||
sub database_is_allowed {
|
||||
|
12
bin/pt-kill
12
bin/pt-kill
@@ -47,7 +47,7 @@ BEGIN {
|
||||
{
|
||||
package Percona::Toolkit;
|
||||
|
||||
our $VERSION = '2.2.3';
|
||||
our $VERSION = '2.2.4';
|
||||
|
||||
use strict;
|
||||
use warnings FATAL => 'all';
|
||||
@@ -1110,7 +1110,7 @@ sub set_vars {
|
||||
if ( $user_vars ) {
|
||||
foreach my $var_val ( @$user_vars ) {
|
||||
my ($var, $val) = $var_val =~ m/([^\s=]+)=(\S+)/;
|
||||
die "Invalid --set-vars value: $var_val\n" unless $var && $val;
|
||||
die "Invalid --set-vars value: $var_val\n" unless $var && defined $val;
|
||||
$user_vars{$var} = {
|
||||
val => $val,
|
||||
default => 0,
|
||||
@@ -1124,7 +1124,7 @@ sub set_vars {
|
||||
%default_vars = map {
|
||||
my $var_val = $_;
|
||||
my ($var, $val) = $var_val =~ m/([^\s=]+)=(\S+)/;
|
||||
die "Invalid --set-vars value: $var_val\n" unless $var && $val;
|
||||
die "Invalid --set-vars value: $var_val\n" unless $var && defined $val;
|
||||
$var => {
|
||||
val => $val,
|
||||
default => 1,
|
||||
@@ -4655,8 +4655,8 @@ sub new {
|
||||
sub strip_comments {
|
||||
my ( $self, $query ) = @_;
|
||||
return unless $query;
|
||||
$query =~ s/$olc_re//go;
|
||||
$query =~ s/$mlc_re//go;
|
||||
$query =~ s/$olc_re//go;
|
||||
if ( $query =~ m/$vlc_rf/i ) { # contains show + version
|
||||
$query =~ s/$vlc_re//go;
|
||||
}
|
||||
@@ -4723,9 +4723,9 @@ sub fingerprint {
|
||||
if ( my ($beginning) = $query =~ m/\A((?:INSERT|REPLACE)(?: IGNORE)?\s+INTO.+?VALUES\s*\(.*?\))\s*,\s*\(/is ) {
|
||||
$query = $beginning; # Shorten multi-value INSERT statements ASAP
|
||||
}
|
||||
|
||||
$query =~ s/$olc_re//go;
|
||||
|
||||
$query =~ s/$mlc_re//go;
|
||||
$query =~ s/$olc_re//go;
|
||||
$query =~ s/\Ause \S+\Z/use ?/i # Abstract the DB in USE
|
||||
&& return $query;
|
||||
|
||||
|
@@ -54,7 +54,7 @@ BEGIN {
|
||||
{
|
||||
package Percona::Toolkit;
|
||||
|
||||
our $VERSION = '2.2.3';
|
||||
our $VERSION = '2.2.4';
|
||||
|
||||
use strict;
|
||||
use warnings FATAL => 'all';
|
||||
@@ -1117,7 +1117,7 @@ sub set_vars {
|
||||
if ( $user_vars ) {
|
||||
foreach my $var_val ( @$user_vars ) {
|
||||
my ($var, $val) = $var_val =~ m/([^\s=]+)=(\S+)/;
|
||||
die "Invalid --set-vars value: $var_val\n" unless $var && $val;
|
||||
die "Invalid --set-vars value: $var_val\n" unless $var && defined $val;
|
||||
$user_vars{$var} = {
|
||||
val => $val,
|
||||
default => 0,
|
||||
@@ -1131,7 +1131,7 @@ sub set_vars {
|
||||
%default_vars = map {
|
||||
my $var_val = $_;
|
||||
my ($var, $val) = $var_val =~ m/([^\s=]+)=(\S+)/;
|
||||
die "Invalid --set-vars value: $var_val\n" unless $var && $val;
|
||||
die "Invalid --set-vars value: $var_val\n" unless $var && defined $val;
|
||||
$var => {
|
||||
val => $val,
|
||||
default => 1,
|
||||
@@ -5495,7 +5495,7 @@ sub _find_best_index {
|
||||
}
|
||||
@possible_indexes = sort {
|
||||
my $cmp
|
||||
= $indexes->{$b}->{cardinality} <=> $indexes->{$b}->{cardinality};
|
||||
= $indexes->{$b}->{cardinality} <=> $indexes->{$a}->{cardinality};
|
||||
if ( $cmp == 0 ) {
|
||||
$cmp = scalar @{$indexes->{$b}->{cols}}
|
||||
<=> scalar @{$indexes->{$a}->{cols}};
|
||||
@@ -8477,17 +8477,17 @@ sub main {
|
||||
. " doesn't exist\".\n";
|
||||
}
|
||||
else {
|
||||
print "Dropping new table...\n";
|
||||
print ts("Dropping new table...\n");
|
||||
print $sql, "\n" if $o->get('print');
|
||||
PTDEBUG && _d($sql);
|
||||
eval {
|
||||
$cxn->dbh()->do($sql);
|
||||
};
|
||||
if ( $EVAL_ERROR ) {
|
||||
warn "Error dropping new table $new_tbl->{name}: $EVAL_ERROR\n"
|
||||
. "To try dropping the new table again, execute:\n$sql\n";
|
||||
warn ts("Error dropping new table $new_tbl->{name}: $EVAL_ERROR\n"
|
||||
. "To try dropping the new table again, execute:\n$sql\n");
|
||||
}
|
||||
print "Dropped new table OK.\n";
|
||||
print ts("Dropped new table OK.\n");
|
||||
}
|
||||
};
|
||||
|
||||
@@ -8737,8 +8737,8 @@ sub main {
|
||||
return;
|
||||
}
|
||||
else {
|
||||
print "Copying approximately ", $nibble_iter->row_estimate(),
|
||||
" rows...\n";
|
||||
print ts("Copying approximately "
|
||||
. $nibble_iter->row_estimate() . " rows...\n");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8784,7 +8784,7 @@ sub main {
|
||||
. ($tbl->{chunk_size} * $limit)
|
||||
. " rows (chunk size=$tbl->{chunk_size}"
|
||||
. " * chunk size limit=$limit).\n";
|
||||
die $msg;
|
||||
die ts($msg);
|
||||
}
|
||||
}
|
||||
else { # chunking the table
|
||||
@@ -8797,20 +8797,20 @@ sub main {
|
||||
n_index_cols => $o->get('chunk-index-columns'),
|
||||
);
|
||||
if ( !$key || lc($key) ne lc($nibble_iter->nibble_index()) ) {
|
||||
die "Cannot determine the key_len of the chunk index "
|
||||
die ts("Cannot determine the key_len of the chunk index "
|
||||
. "because MySQL chose "
|
||||
. ($key ? "the $key" : "no") . " index "
|
||||
. "instead of the " . $nibble_iter->nibble_index()
|
||||
. " index for the first lower boundary statement. "
|
||||
. "See --[no]check-plan in the documentation for more "
|
||||
. "information.";
|
||||
. "information.");
|
||||
}
|
||||
elsif ( !$key_len ) {
|
||||
die "The key_len of the $key index is "
|
||||
die ts("The key_len of the $key index is "
|
||||
. (defined $key_len ? "zero" : "NULL")
|
||||
. ", but this should not be possible. "
|
||||
. "See --[no]check-plan in the documentation for more "
|
||||
. "information.";
|
||||
. "information.");
|
||||
}
|
||||
$tbl->{key_len} = $key_len;
|
||||
}
|
||||
@@ -8852,7 +8852,7 @@ sub main {
|
||||
. join(", ", map { defined $_ ? $_ : "NULL" }
|
||||
(@{$boundary->{lower}}, $nibble_iter->limit()))
|
||||
. "\n";
|
||||
die $msg;
|
||||
die ts($msg);
|
||||
}
|
||||
|
||||
# Once nibbling begins for a table, control does not return to this
|
||||
@@ -8926,13 +8926,13 @@ sub main {
|
||||
|
||||
# This warning is printed once per table.
|
||||
if ( !$tbl->{warned_slow} ) {
|
||||
warn "Rows are copying very slowly. "
|
||||
warn ts("Rows are copying very slowly. "
|
||||
. "--chunk-size has been automatically reduced to 1. "
|
||||
. "Check that the server is not being overloaded, "
|
||||
. "or increase --chunk-time. The last chunk "
|
||||
. "selected $cnt rows and took "
|
||||
. sprintf('%.3f', $tbl->{nibble_time})
|
||||
. " seconds to execute.\n";
|
||||
. " seconds to execute.\n");
|
||||
$tbl->{warned_slow} = 1;
|
||||
}
|
||||
}
|
||||
@@ -8960,7 +8960,7 @@ sub main {
|
||||
},
|
||||
done => sub {
|
||||
if ( $o->get('execute') ) {
|
||||
print "Copied rows OK.\n";
|
||||
print ts("Copied rows OK.\n");
|
||||
}
|
||||
},
|
||||
};
|
||||
@@ -9027,8 +9027,8 @@ sub main {
|
||||
1 while $nibble_iter->next();
|
||||
};
|
||||
if ( $EVAL_ERROR ) {
|
||||
die "Error copying rows from $orig_tbl->{name} to "
|
||||
. "$new_tbl->{name}: $EVAL_ERROR\n";
|
||||
die ts("Error copying rows from $orig_tbl->{name} to "
|
||||
. "$new_tbl->{name}: $EVAL_ERROR\n");
|
||||
}
|
||||
$orig_tbl->{copied} = 1; # flag for cleanup tasks
|
||||
|
||||
@@ -9097,10 +9097,10 @@ sub main {
|
||||
};
|
||||
if ( $EVAL_ERROR ) {
|
||||
# TODO: one of these values can be undefined
|
||||
die "Error swapping tables: $EVAL_ERROR\n"
|
||||
die ts("Error swapping tables: $EVAL_ERROR\n"
|
||||
. "To clean up, first verify that the original table "
|
||||
. "$orig_tbl->{name} has not been modified or renamed, "
|
||||
. "then drop the new table $new_tbl->{name} if it exists.\n";
|
||||
. "then drop the new table $new_tbl->{name} if it exists.\n");
|
||||
}
|
||||
}
|
||||
$orig_tbl->{swapped} = 1; # flag for cleanup tasks
|
||||
@@ -9192,7 +9192,7 @@ sub main {
|
||||
$plugin->before_drop_old_table();
|
||||
}
|
||||
|
||||
print "Dropping old table...\n";
|
||||
print ts("Dropping old table...\n");
|
||||
|
||||
if ( $alter_fk_method eq 'none' ) {
|
||||
# Child tables still reference the old table, but the user
|
||||
@@ -9211,9 +9211,9 @@ sub main {
|
||||
$cxn->dbh()->do($sql);
|
||||
};
|
||||
if ( $EVAL_ERROR ) {
|
||||
die "Error dropping the old table: $EVAL_ERROR\n";
|
||||
die ts("Error dropping the old table: $EVAL_ERROR\n");
|
||||
}
|
||||
print "Dropped old table $old_tbl->{name} OK.\n";
|
||||
print ts("Dropped old table $old_tbl->{name} OK.\n");
|
||||
|
||||
# --plugin hook
|
||||
if ( $plugin && $plugin->can('after_drop_old_table') ) {
|
||||
@@ -9453,10 +9453,10 @@ sub nibble_is_safe {
|
||||
if ( !$nibble_iter->one_nibble()
|
||||
&& lc($expl->{key} || '') ne lc($nibble_iter->nibble_index() || '') )
|
||||
{
|
||||
die "Error copying rows at chunk " . $nibble_iter->nibble_number()
|
||||
die ts("Error copying rows at chunk " . $nibble_iter->nibble_number()
|
||||
. " of $tbl->{db}.$tbl->{tbl} because MySQL chose "
|
||||
. ($expl->{key} ? "the $expl->{key}" : "no") . " index "
|
||||
. " instead of the " . $nibble_iter->nibble_index() . "index.\n";
|
||||
. " instead of the " . $nibble_iter->nibble_index() . "index.\n");
|
||||
}
|
||||
|
||||
# Ensure that the chunk isn't too large if there's a --chunk-size-limit.
|
||||
@@ -9471,14 +9471,14 @@ sub nibble_is_safe {
|
||||
&& $nibble_iter->identical_boundaries($boundary->{upper},
|
||||
$boundary->{next_lower}) )
|
||||
{
|
||||
die "Error copying rows at chunk " . $nibble_iter->nibble_number()
|
||||
die ts("Error copying rows at chunk " . $nibble_iter->nibble_number()
|
||||
. " of $tbl->{db}.$tbl->{tbl} because it is oversized. "
|
||||
. "The current chunk size limit is "
|
||||
. ($tbl->{chunk_size} * $limit)
|
||||
. " rows (chunk size=$tbl->{chunk_size}"
|
||||
. " * chunk size limit=$limit), but MySQL estimates "
|
||||
. "that there are " . ($expl->{rows} || 0)
|
||||
. " rows in the chunk.\n";
|
||||
. " rows in the chunk.\n");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9488,12 +9488,12 @@ sub nibble_is_safe {
|
||||
&& $tbl->{key_len}
|
||||
&& ($expl->{key_len} || 0) < $tbl->{key_len} )
|
||||
{
|
||||
die "Error copying rows at chunk " . $nibble_iter->nibble_number()
|
||||
die ts("Error copying rows at chunk " . $nibble_iter->nibble_number()
|
||||
. " of $tbl->{db}.$tbl->{tbl} because MySQL used "
|
||||
. "only " . ($expl->{key_len} || 0) . " bytes "
|
||||
. "of the " . ($expl->{key} || '?') . " index instead of "
|
||||
. $tbl->{key_len} . ". See the --[no]check-plan documentation "
|
||||
. "for more information.\n";
|
||||
. "for more information.\n");
|
||||
}
|
||||
|
||||
return 1; # safe
|
||||
@@ -9613,22 +9613,20 @@ sub swap_tables {
|
||||
return $orig_tbl;
|
||||
}
|
||||
elsif ( $o->get('execute') ) {
|
||||
print "Swapping tables...\n";
|
||||
print ts("Swapping tables...\n");
|
||||
|
||||
while ( $name_tries-- ) {
|
||||
$table_name = $prefix . $table_name;
|
||||
|
||||
if ( length($table_name) > 64 ) {
|
||||
my $truncated_table_name = substr($table_name, 0, 64);
|
||||
PTDEBUG && _d($table_name, 'is over 64 characters long, truncating to',
|
||||
PTDEBUG && _d($table_name, 'is > 64 chars, truncating to',
|
||||
$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}";
|
||||
|
||||
my $sql = "RENAME TABLE $orig_tbl->{name} "
|
||||
. "TO " . $q->quote($orig_tbl->{db}, $table_name)
|
||||
. ", $new_tbl->{name} TO $orig_tbl->{name}";
|
||||
eval {
|
||||
osc_retry(
|
||||
Cxn => $cxn,
|
||||
@@ -9655,11 +9653,12 @@ sub swap_tables {
|
||||
PTDEBUG && _d($e);
|
||||
next;
|
||||
}
|
||||
die $e;
|
||||
die ts($e);
|
||||
}
|
||||
|
||||
print $sql, "\n" if $o->get('print');
|
||||
print "Swapped original and new tables OK.\n";
|
||||
print ts("Swapped original and new tables OK.\n");
|
||||
|
||||
return { # success
|
||||
db => $orig_tbl->{db},
|
||||
tbl => $table_name,
|
||||
@@ -9670,7 +9669,8 @@ sub swap_tables {
|
||||
# This shouldn't happen.
|
||||
# Here and in the attempt to find a new table name we probably ought to
|
||||
# use --tries (and maybe a Retry object?)
|
||||
die "Failed to find a unique old table name after serveral attempts.\n";
|
||||
die ts("Failed to find a unique old table name after "
|
||||
. "serveral attempts.\n");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9794,10 +9794,10 @@ sub determine_alter_fk_method {
|
||||
# and doesn't cause the orig table to go missing for a moment.
|
||||
my $method = 'rebuild_constraints';
|
||||
|
||||
print "Max rows for the rebuild_constraints method: $max_rows\n",
|
||||
"Determining the method to update foreign keys...\n";
|
||||
print ts("Max rows for the rebuild_constraints method: $max_rows\n"
|
||||
. "Determining the method to update foreign keys...\n");
|
||||
foreach my $child_tbl ( @$child_tables ) {
|
||||
print " $child_tbl->{name}: ";
|
||||
print ts(" $child_tbl->{name}: ");
|
||||
my ($n_rows) = NibbleIterator::get_row_estimate(
|
||||
Cxn => $cxn,
|
||||
tbl => $child_tbl,
|
||||
@@ -9846,7 +9846,7 @@ sub rebuild_constraints {
|
||||
print "Not rebuilding foreign key constraints because this is a dry run.\n";
|
||||
}
|
||||
else {
|
||||
print "Rebuilding foreign key constraints...\n";
|
||||
print ts("Rebuilding foreign key constraints...\n");
|
||||
}
|
||||
|
||||
CHILD_TABLE:
|
||||
@@ -9858,8 +9858,8 @@ sub rebuild_constraints {
|
||||
);
|
||||
my @constraints = $table_def =~ m/$constraint/g;
|
||||
if ( !@constraints ) {
|
||||
warn "$child_tbl->{name} has no foreign key "
|
||||
. "constraints referencing $old_tbl->{name}.\n";
|
||||
warn ts("$child_tbl->{name} has no foreign key "
|
||||
. "constraints referencing $old_tbl->{name}.\n");
|
||||
next CHILD_TABLE;
|
||||
}
|
||||
|
||||
@@ -9913,7 +9913,7 @@ sub rebuild_constraints {
|
||||
}
|
||||
|
||||
if ( $o->get('execute') ) {
|
||||
print "Rebuilt foreign key constraints OK.\n";
|
||||
print ts("Rebuilt foreign key constraints OK.\n");
|
||||
}
|
||||
|
||||
return;
|
||||
@@ -9931,7 +9931,7 @@ sub drop_swap {
|
||||
print "Not drop-swapping tables because this is a dry run.\n";
|
||||
}
|
||||
else {
|
||||
print "Drop-swapping tables...\n";
|
||||
print ts("Drop-swapping tables...\n");
|
||||
}
|
||||
|
||||
my @sqls = (
|
||||
@@ -9958,7 +9958,7 @@ sub drop_swap {
|
||||
}
|
||||
|
||||
if ( $o->get('execute') ) {
|
||||
print "Dropped and swapped tables OK.\n";
|
||||
print ts("Dropped and swapped tables OK.\n");
|
||||
}
|
||||
|
||||
return;
|
||||
@@ -9979,7 +9979,7 @@ sub create_triggers {
|
||||
print "Not creating triggers because this is a dry run.\n";
|
||||
}
|
||||
else {
|
||||
print "Creating triggers...\n";
|
||||
print ts("Creating triggers...\n");
|
||||
}
|
||||
|
||||
# Create a unique trigger name prefix based on the orig table name
|
||||
@@ -10059,7 +10059,7 @@ sub create_triggers {
|
||||
}
|
||||
|
||||
if ( $o->get('execute') ) {
|
||||
print "Created triggers OK.\n";
|
||||
print ts("Created triggers OK.\n");
|
||||
}
|
||||
|
||||
return @trigger_names;
|
||||
@@ -10080,7 +10080,7 @@ sub drop_triggers {
|
||||
print "Not dropping triggers because this is a dry run.\n";
|
||||
}
|
||||
else {
|
||||
print "Dropping triggers...\n";
|
||||
print ts("Dropping triggers...\n");
|
||||
}
|
||||
|
||||
foreach my $sql ( @drop_trigger_sqls ) {
|
||||
@@ -10099,7 +10099,7 @@ sub drop_triggers {
|
||||
);
|
||||
};
|
||||
if ( $EVAL_ERROR ) {
|
||||
warn "Error dropping trigger: $EVAL_ERROR\n";
|
||||
warn ts("Error dropping trigger: $EVAL_ERROR\n");
|
||||
push @triggers_not_dropped, $sql;
|
||||
$exit_status = 1;
|
||||
}
|
||||
@@ -10108,11 +10108,11 @@ sub drop_triggers {
|
||||
|
||||
if ( $o->get('execute') ) {
|
||||
if ( !@triggers_not_dropped ) {
|
||||
print "Dropped triggers OK.\n";
|
||||
print ts("Dropped triggers OK.\n");
|
||||
}
|
||||
else {
|
||||
warn "To try dropping the triggers again, execute:\n"
|
||||
. join("\n", @triggers_not_dropped) . "\n";
|
||||
warn ts("To try dropping the triggers again, execute:\n"
|
||||
. join("\n", @triggers_not_dropped) . "\n");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10192,7 +10192,7 @@ sub osc_retry {
|
||||
# the tool will stop, which is probably good because by this
|
||||
# point the error or warning indicates that something is wrong.
|
||||
$stats->{ error_event($error) }++;
|
||||
die $error;
|
||||
die ts($error);
|
||||
}
|
||||
);
|
||||
}
|
||||
@@ -10285,22 +10285,14 @@ sub exec_nibble {
|
||||
|| $message =~ m/$warn_code{$code}->{pattern}/) )
|
||||
{
|
||||
if ( !$stats->{"mysql_warning_$code"}++ ) { # warn once
|
||||
my $err
|
||||
= "Copying rows caused a MySQL error $code: "
|
||||
warn "Copying rows caused a MySQL error $code: "
|
||||
. ($warn_code{$code}->{message}
|
||||
? $warn_code{$code}->{message}
|
||||
: $message)
|
||||
. "\nThis MySQL error is being ignored ";
|
||||
if ( get('statistics') ) {
|
||||
$err .= "but further occurrences will be reported "
|
||||
. "by --statistics when the tool finishes.\n";
|
||||
}
|
||||
else {
|
||||
$err .= "and further occurrences will not be reported. "
|
||||
. "Specify --statistics to see a count of all "
|
||||
. "suppressed warnings and errors.\n";
|
||||
}
|
||||
warn $err;
|
||||
. "\nNo more warnings about this MySQL error will be "
|
||||
. "reported. If --statistics was specified, "
|
||||
. "mysql_warning_$code will list the total count of "
|
||||
. "this MySQL error.\n";
|
||||
}
|
||||
}
|
||||
else {
|
||||
@@ -10354,6 +10346,12 @@ sub explain_statement {
|
||||
return $expl;
|
||||
}
|
||||
|
||||
sub ts {
|
||||
my ($msg) = @_;
|
||||
my $ts = $ENV{PTTEST_FAKE_TS} ? 'TS' : Transformers::ts(int(time));
|
||||
return $msg ? "$ts $msg" : $ts;
|
||||
}
|
||||
|
||||
# Catches signals so we can exit gracefully.
|
||||
sub sig_int {
|
||||
my ( $signal ) = @_;
|
||||
|
@@ -64,7 +64,7 @@ BEGIN {
|
||||
{
|
||||
package Percona::Toolkit;
|
||||
|
||||
our $VERSION = '2.2.3';
|
||||
our $VERSION = '2.2.4';
|
||||
|
||||
use strict;
|
||||
use warnings FATAL => 'all';
|
||||
@@ -2350,7 +2350,7 @@ sub set_vars {
|
||||
if ( $user_vars ) {
|
||||
foreach my $var_val ( @$user_vars ) {
|
||||
my ($var, $val) = $var_val =~ m/([^\s=]+)=(\S+)/;
|
||||
die "Invalid --set-vars value: $var_val\n" unless $var && $val;
|
||||
die "Invalid --set-vars value: $var_val\n" unless $var && defined $val;
|
||||
$user_vars{$var} = {
|
||||
val => $val,
|
||||
default => 0,
|
||||
@@ -2364,7 +2364,7 @@ sub set_vars {
|
||||
%default_vars = map {
|
||||
my $var_val = $_;
|
||||
my ($var, $val) = $var_val =~ m/([^\s=]+)=(\S+)/;
|
||||
die "Invalid --set-vars value: $var_val\n" unless $var && $val;
|
||||
die "Invalid --set-vars value: $var_val\n" unless $var && defined $val;
|
||||
$var => {
|
||||
val => $val,
|
||||
default => 1,
|
||||
@@ -2802,8 +2802,8 @@ sub new {
|
||||
sub strip_comments {
|
||||
my ( $self, $query ) = @_;
|
||||
return unless $query;
|
||||
$query =~ s/$olc_re//go;
|
||||
$query =~ s/$mlc_re//go;
|
||||
$query =~ s/$olc_re//go;
|
||||
if ( $query =~ m/$vlc_rf/i ) { # contains show + version
|
||||
$query =~ s/$vlc_re//go;
|
||||
}
|
||||
@@ -2870,9 +2870,9 @@ sub fingerprint {
|
||||
if ( my ($beginning) = $query =~ m/\A((?:INSERT|REPLACE)(?: IGNORE)?\s+INTO.+?VALUES\s*\(.*?\))\s*,\s*\(/is ) {
|
||||
$query = $beginning; # Shorten multi-value INSERT statements ASAP
|
||||
}
|
||||
|
||||
$query =~ s/$olc_re//go;
|
||||
|
||||
$query =~ s/$mlc_re//go;
|
||||
$query =~ s/$olc_re//go;
|
||||
$query =~ s/\Ause \S+\Z/use ?/i # Abstract the DB in USE
|
||||
&& return $query;
|
||||
|
||||
@@ -7900,10 +7900,12 @@ override query_report => sub {
|
||||
distillate => $distill,
|
||||
attribute => $groupby,
|
||||
query_count => $times_seen,
|
||||
example => {
|
||||
query => substr($sample->{arg}, 0, $self->max_query_length),
|
||||
ts => $sample->{ts} ? parse_timestamp($sample->{ts}) : undef,
|
||||
},
|
||||
$args{anon} ? () : (
|
||||
example => {
|
||||
query => substr($sample->{arg}, 0, $self->max_query_length),
|
||||
ts => $sample->{ts} ? parse_timestamp($sample->{ts}) : undef,
|
||||
},
|
||||
),
|
||||
};
|
||||
|
||||
my %metrics;
|
||||
@@ -7981,19 +7983,21 @@ override query_report => sub {
|
||||
push @tables, { status => $status, create => $create };
|
||||
}
|
||||
|
||||
if ( $item =~ m/^(?:[\(\s]*select|insert|replace)/ ) {
|
||||
if ( $item =~ m/^(?:insert|replace)/ ) {
|
||||
if ( !$args{anon} ) {
|
||||
if ( $item =~ m/^(?:[\(\s]*select|insert|replace)/ ) {
|
||||
if ( $item =~ m/^(?:insert|replace)/ ) {
|
||||
}
|
||||
else {
|
||||
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
||||
}
|
||||
}
|
||||
else {
|
||||
my $converted = $qr->convert_to_select(
|
||||
$sample->{arg} || '',
|
||||
);
|
||||
if ( $converted && $converted =~ m/^[\(\s]*select/i ) {
|
||||
$class->{example}->{as_select} = $converted;
|
||||
my $converted = $qr->convert_to_select(
|
||||
$sample->{arg} || '',
|
||||
);
|
||||
if ( $converted && $converted =~ m/^[\(\s]*select/i ) {
|
||||
$class->{example}->{as_select} = $converted;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -13252,7 +13256,10 @@ sub main {
|
||||
process => sub {
|
||||
my ( $args ) = @_;
|
||||
my $event = $pl->parse_event(code => $code);
|
||||
$args->{event} = $event if $event;
|
||||
if ( $event ) {
|
||||
sanitize_event($event);
|
||||
$args->{event} = $event;
|
||||
}
|
||||
return $args;
|
||||
},
|
||||
);
|
||||
@@ -13313,6 +13320,7 @@ sub main {
|
||||
stats => $args->{stats},
|
||||
);
|
||||
if ( $event ) {
|
||||
sanitize_event($event);
|
||||
$args->{event} = $event;
|
||||
return $args;
|
||||
}
|
||||
@@ -14151,7 +14159,7 @@ sub print_reports {
|
||||
$print_header = 1;
|
||||
}
|
||||
|
||||
my $report_class = $o->get('output') =~ m/\Ajson\z/i
|
||||
my $report_class = $o->get('output') =~ m/^json/i
|
||||
? 'JSONReportFormatter'
|
||||
: 'QueryReportFormatter';
|
||||
my $qrf = $report_class->new(
|
||||
@@ -14178,6 +14186,7 @@ sub print_reports {
|
||||
variations => $o->get('variations'),
|
||||
group => { map { $_=>1 } qw(rusage date hostname files header) },
|
||||
resume => $resume,
|
||||
anon => $o->get('output') eq 'json-anon',
|
||||
);
|
||||
}
|
||||
|
||||
@@ -14567,6 +14576,23 @@ sub save_resume_offset {
|
||||
return;
|
||||
}
|
||||
|
||||
sub sanitize_event {
|
||||
my ($event) = @_;
|
||||
|
||||
# Quoted and unquoted values should be treated the same
|
||||
# https://bugs.launchpad.net/percona-toolkit/+bug/1176010
|
||||
if ( $event->{db} ) {
|
||||
$event->{db} =~ s/^`//;
|
||||
$event->{db} =~ s/`$//;
|
||||
}
|
||||
if ( $event->{Schema} ) {
|
||||
$event->{Schema} =~ s/^`//;
|
||||
$event->{Schema} =~ s/`$//;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
sub _d {
|
||||
my ($package, undef, $line) = caller 0;
|
||||
@_ = map { (my $temp = $_) =~ s/\n/\n# /g; $temp; }
|
||||
@@ -15590,11 +15616,12 @@ type: string; default: report
|
||||
|
||||
How to format and print the query analysis results. Accepted values are:
|
||||
|
||||
VALUE FORMAT
|
||||
======= ==============================
|
||||
report Standard query analysis report
|
||||
slowlog MySQL slow log
|
||||
json JSON, on array per query class
|
||||
VALUE FORMAT
|
||||
======= ==============================
|
||||
report Standard query analysis report
|
||||
slowlog MySQL slow log
|
||||
json JSON, on array per query class
|
||||
json-anon JSON without example queries
|
||||
|
||||
The entire C<report> output can be disabled by specifying C<--no-report>
|
||||
(see L<"--[no]report">), and its sections can be disabled or rearranged
|
||||
@@ -16051,6 +16078,23 @@ database.
|
||||
Server-side prepared statements are supported. SSL-encrypted traffic cannot be
|
||||
inspected and decoded.
|
||||
|
||||
=item rawlog
|
||||
|
||||
Raw logs are not MySQL logs but simple text files with one SQL statement
|
||||
per line, like:
|
||||
|
||||
SELECT c FROM t WHERE id=1
|
||||
/* Hello, world! */ SELECT * FROM t2 LIMIT 1
|
||||
INSERT INTO t (a, b) VALUES ('foo', 'bar')
|
||||
INSERT INTO t SELECT * FROM monkeys
|
||||
|
||||
Since raw logs do not have any metrics, many options and features of
|
||||
pt-query-digest do not work with them.
|
||||
|
||||
One use case for raw logs is ranking queries by count when the only
|
||||
information available is a list of queries, from polling C<SHOW PROCESSLIST>
|
||||
for example.
|
||||
|
||||
=back
|
||||
|
||||
=item --until
|
||||
|
@@ -1030,7 +1030,7 @@ sub set_vars {
|
||||
if ( $user_vars ) {
|
||||
foreach my $var_val ( @$user_vars ) {
|
||||
my ($var, $val) = $var_val =~ m/([^\s=]+)=(\S+)/;
|
||||
die "Invalid --set-vars value: $var_val\n" unless $var && $val;
|
||||
die "Invalid --set-vars value: $var_val\n" unless $var && defined $val;
|
||||
$user_vars{$var} = {
|
||||
val => $val,
|
||||
default => 0,
|
||||
@@ -1044,7 +1044,7 @@ sub set_vars {
|
||||
%default_vars = map {
|
||||
my $var_val = $_;
|
||||
my ($var, $val) = $var_val =~ m/([^\s=]+)=(\S+)/;
|
||||
die "Invalid --set-vars value: $var_val\n" unless $var && $val;
|
||||
die "Invalid --set-vars value: $var_val\n" unless $var && defined $val;
|
||||
$var => {
|
||||
val => $val,
|
||||
default => 1,
|
||||
|
@@ -545,7 +545,7 @@ main() {
|
||||
if [ -d "$1" ]; then
|
||||
BASEDIR="$1"
|
||||
PREFIX=""
|
||||
elif [ -f "$1" -o -f "$1-df" -o -f "$1df" ]; then
|
||||
elif [ -f "$1" -o -f "$1-output" -o -f "$1output" ]; then
|
||||
BASEDIR="$(dirname "$1")"
|
||||
PREFIX="$(echo "$1" | perl -ne '$_ =~ m/([\d_]+)/; print $1;')"
|
||||
else
|
||||
@@ -578,10 +578,10 @@ main() {
|
||||
done
|
||||
|
||||
# We need to generate a list of timestamps, and ask the user to choose one if
|
||||
# there is no PREFIX yet. NOTE: we rely on the "-df" files here.
|
||||
# there is no PREFIX yet. NOTE: we rely on the "-output" files here.
|
||||
(
|
||||
cd "$BASEDIR"
|
||||
ls *-df 2>/dev/null | cut -d- -f1 | sort > "$PT_TMPDIR/pt-sift.prefixes"
|
||||
ls *-output 2>/dev/null | cut -d- -f1 | sort > "$PT_TMPDIR/pt-sift.prefixes"
|
||||
)
|
||||
if [ ! -s "$PT_TMPDIR/pt-sift.prefixes" ]; then
|
||||
echo "Error: There are no pt-stalk files in $BASEDIR" >&2
|
||||
|
@@ -40,7 +40,7 @@ BEGIN {
|
||||
{
|
||||
package Percona::Toolkit;
|
||||
|
||||
our $VERSION = '2.2.3';
|
||||
our $VERSION = '2.2.4';
|
||||
|
||||
use strict;
|
||||
use warnings FATAL => 'all';
|
||||
@@ -1103,7 +1103,7 @@ sub set_vars {
|
||||
if ( $user_vars ) {
|
||||
foreach my $var_val ( @$user_vars ) {
|
||||
my ($var, $val) = $var_val =~ m/([^\s=]+)=(\S+)/;
|
||||
die "Invalid --set-vars value: $var_val\n" unless $var && $val;
|
||||
die "Invalid --set-vars value: $var_val\n" unless $var && defined $val;
|
||||
$user_vars{$var} = {
|
||||
val => $val,
|
||||
default => 0,
|
||||
@@ -1117,7 +1117,7 @@ sub set_vars {
|
||||
%default_vars = map {
|
||||
my $var_val = $_;
|
||||
my ($var, $val) = $var_val =~ m/([^\s=]+)=(\S+)/;
|
||||
die "Invalid --set-vars value: $var_val\n" unless $var && $val;
|
||||
die "Invalid --set-vars value: $var_val\n" unless $var && defined $val;
|
||||
$var => {
|
||||
val => $val,
|
||||
default => 1,
|
||||
|
@@ -1038,7 +1038,7 @@ sub set_vars {
|
||||
if ( $user_vars ) {
|
||||
foreach my $var_val ( @$user_vars ) {
|
||||
my ($var, $val) = $var_val =~ m/([^\s=]+)=(\S+)/;
|
||||
die "Invalid --set-vars value: $var_val\n" unless $var && $val;
|
||||
die "Invalid --set-vars value: $var_val\n" unless $var && defined $val;
|
||||
$user_vars{$var} = {
|
||||
val => $val,
|
||||
default => 0,
|
||||
@@ -1052,7 +1052,7 @@ sub set_vars {
|
||||
%default_vars = map {
|
||||
my $var_val = $_;
|
||||
my ($var, $val) = $var_val =~ m/([^\s=]+)=(\S+)/;
|
||||
die "Invalid --set-vars value: $var_val\n" unless $var && $val;
|
||||
die "Invalid --set-vars value: $var_val\n" unless $var && defined $val;
|
||||
$var => {
|
||||
val => $val,
|
||||
default => 1,
|
||||
|
@@ -41,7 +41,7 @@ BEGIN {
|
||||
{
|
||||
package Percona::Toolkit;
|
||||
|
||||
our $VERSION = '2.2.3';
|
||||
our $VERSION = '2.2.4';
|
||||
|
||||
use strict;
|
||||
use warnings FATAL => 'all';
|
||||
@@ -1255,7 +1255,7 @@ sub set_vars {
|
||||
if ( $user_vars ) {
|
||||
foreach my $var_val ( @$user_vars ) {
|
||||
my ($var, $val) = $var_val =~ m/([^\s=]+)=(\S+)/;
|
||||
die "Invalid --set-vars value: $var_val\n" unless $var && $val;
|
||||
die "Invalid --set-vars value: $var_val\n" unless $var && defined $val;
|
||||
$user_vars{$var} = {
|
||||
val => $val,
|
||||
default => 0,
|
||||
@@ -1269,7 +1269,7 @@ sub set_vars {
|
||||
%default_vars = map {
|
||||
my $var_val = $_;
|
||||
my ($var, $val) = $var_val =~ m/([^\s=]+)=(\S+)/;
|
||||
die "Invalid --set-vars value: $var_val\n" unless $var && $val;
|
||||
die "Invalid --set-vars value: $var_val\n" unless $var && defined $val;
|
||||
$var => {
|
||||
val => $val,
|
||||
default => 1,
|
||||
|
@@ -57,7 +57,7 @@ BEGIN {
|
||||
{
|
||||
package Percona::Toolkit;
|
||||
|
||||
our $VERSION = '2.2.3';
|
||||
our $VERSION = '2.2.4';
|
||||
|
||||
use strict;
|
||||
use warnings FATAL => 'all';
|
||||
@@ -2784,7 +2784,7 @@ sub set_vars {
|
||||
if ( $user_vars ) {
|
||||
foreach my $var_val ( @$user_vars ) {
|
||||
my ($var, $val) = $var_val =~ m/([^\s=]+)=(\S+)/;
|
||||
die "Invalid --set-vars value: $var_val\n" unless $var && $val;
|
||||
die "Invalid --set-vars value: $var_val\n" unless $var && defined $val;
|
||||
$user_vars{$var} = {
|
||||
val => $val,
|
||||
default => 0,
|
||||
@@ -2798,7 +2798,7 @@ sub set_vars {
|
||||
%default_vars = map {
|
||||
my $var_val = $_;
|
||||
my ($var, $val) = $var_val =~ m/([^\s=]+)=(\S+)/;
|
||||
die "Invalid --set-vars value: $var_val\n" unless $var && $val;
|
||||
die "Invalid --set-vars value: $var_val\n" unless $var && defined $val;
|
||||
$var => {
|
||||
val => $val,
|
||||
default => 1,
|
||||
@@ -6479,7 +6479,7 @@ sub _find_best_index {
|
||||
}
|
||||
@possible_indexes = sort {
|
||||
my $cmp
|
||||
= $indexes->{$b}->{cardinality} <=> $indexes->{$b}->{cardinality};
|
||||
= $indexes->{$b}->{cardinality} <=> $indexes->{$a}->{cardinality};
|
||||
if ( $cmp == 0 ) {
|
||||
$cmp = scalar @{$indexes->{$b}->{cols}}
|
||||
<=> scalar @{$indexes->{$a}->{cols}};
|
||||
@@ -7344,58 +7344,63 @@ sub _iterate_dbh {
|
||||
$self->{dbs} = \@dbs;
|
||||
}
|
||||
|
||||
if ( !$self->{db} ) {
|
||||
$self->{db} = shift @{$self->{dbs}};
|
||||
PTDEBUG && _d('Next database:', $self->{db});
|
||||
return unless $self->{db};
|
||||
}
|
||||
|
||||
if ( !defined $self->{tbls} ) {
|
||||
my $sql = 'SHOW /*!50002 FULL*/ TABLES FROM ' . $q->quote($self->{db});
|
||||
PTDEBUG && _d($sql);
|
||||
my @tbls = map {
|
||||
$_->[0]; # (tbl, type)
|
||||
DATABASE:
|
||||
while ( $self->{db} || defined(my $db = shift @{$self->{dbs}}) ) {
|
||||
if ( !$self->{db} ) {
|
||||
PTDEBUG && _d('Next database:', $db);
|
||||
$self->{db} = $db;
|
||||
}
|
||||
grep {
|
||||
my ($tbl, $type) = @$_;
|
||||
(!$type || ($type ne 'VIEW'))
|
||||
&& $self->_resume_from_table($tbl)
|
||||
&& $self->table_is_allowed($self->{db}, $tbl);
|
||||
}
|
||||
@{$dbh->selectall_arrayref($sql)};
|
||||
PTDEBUG && _d('Found', scalar @tbls, 'tables in database', $self->{db});
|
||||
$self->{tbls} = \@tbls;
|
||||
}
|
||||
|
||||
while ( my $tbl = shift @{$self->{tbls}} ) {
|
||||
my $ddl = eval { $tp->get_create_table($dbh, $self->{db}, $tbl) };
|
||||
if ( my $e = $EVAL_ERROR ) {
|
||||
my $table_name = "$self->{db}.$tbl";
|
||||
if ( $e =~ /\QTable '$table_name' doesn't exist/ ) {
|
||||
PTDEBUG && _d("Skipping $table_name because it no longer exists");
|
||||
if ( !$self->{tbls} ) {
|
||||
my $sql = 'SHOW /*!50002 FULL*/ TABLES FROM ' . $q->quote($self->{db});
|
||||
PTDEBUG && _d($sql);
|
||||
my @tbls = map {
|
||||
$_->[0]; # (tbl, type)
|
||||
}
|
||||
else {
|
||||
warn "Skipping $table_name because SHOW CREATE TABLE failed: $e";
|
||||
grep {
|
||||
my ($tbl, $type) = @$_;
|
||||
(!$type || ($type ne 'VIEW'))
|
||||
&& $self->_resume_from_table($tbl)
|
||||
&& $self->table_is_allowed($self->{db}, $tbl);
|
||||
}
|
||||
next;
|
||||
@{$dbh->selectall_arrayref($sql)};
|
||||
PTDEBUG && _d('Found', scalar @tbls, 'tables in database',$self->{db});
|
||||
$self->{tbls} = \@tbls;
|
||||
}
|
||||
my $tbl_struct = $tp->parse($ddl);
|
||||
if ( $self->engine_is_allowed($tbl_struct->{engine}) ) {
|
||||
return {
|
||||
db => $self->{db},
|
||||
tbl => $tbl,
|
||||
name => $q->quote($self->{db}, $tbl),
|
||||
ddl => $ddl,
|
||||
tbl_struct => $tbl_struct,
|
||||
};
|
||||
|
||||
TABLE:
|
||||
while ( my $tbl = shift @{$self->{tbls}} ) {
|
||||
my $ddl = eval { $tp->get_create_table($dbh, $self->{db}, $tbl) };
|
||||
if ( my $e = $EVAL_ERROR ) {
|
||||
my $table_name = "$self->{db}.$tbl";
|
||||
if ( $e =~ /\QTable '$table_name' doesn't exist/ ) {
|
||||
PTDEBUG && _d("$table_name no longer exists");
|
||||
}
|
||||
else {
|
||||
warn "Skipping $table_name because SHOW CREATE TABLE failed: $e";
|
||||
}
|
||||
next TABLE;
|
||||
}
|
||||
|
||||
my $tbl_struct = $tp->parse($ddl);
|
||||
if ( $self->engine_is_allowed($tbl_struct->{engine}) ) {
|
||||
return {
|
||||
db => $self->{db},
|
||||
tbl => $tbl,
|
||||
name => $q->quote($self->{db}, $tbl),
|
||||
ddl => $ddl,
|
||||
tbl_struct => $tbl_struct,
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
PTDEBUG && _d('No more tables in database', $self->{db});
|
||||
$self->{db} = undef;
|
||||
$self->{tbls} = undef;
|
||||
PTDEBUG && _d('No more tables in database', $self->{db});
|
||||
$self->{db} = undef;
|
||||
$self->{tbls} = undef;
|
||||
} # DATABASE
|
||||
|
||||
return $self->_iterate_dbh();
|
||||
PTDEBUG && _d('No more databases');
|
||||
return;
|
||||
}
|
||||
|
||||
sub database_is_allowed {
|
||||
@@ -12037,7 +12042,7 @@ structure (MAGIC_create_replicate):
|
||||
this_cnt int NOT NULL,
|
||||
master_crc char(40) NULL,
|
||||
master_cnt int NULL,
|
||||
ts timestamp NOT NULL,
|
||||
ts timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
PRIMARY KEY (db, tbl, chunk),
|
||||
INDEX ts_db_tbl (ts, db, tbl)
|
||||
) ENGINE=InnoDB;
|
||||
|
@@ -55,7 +55,7 @@ BEGIN {
|
||||
{
|
||||
package Percona::Toolkit;
|
||||
|
||||
our $VERSION = '2.2.3';
|
||||
our $VERSION = '2.2.4';
|
||||
|
||||
use strict;
|
||||
use warnings FATAL => 'all';
|
||||
@@ -1118,7 +1118,7 @@ sub set_vars {
|
||||
if ( $user_vars ) {
|
||||
foreach my $var_val ( @$user_vars ) {
|
||||
my ($var, $val) = $var_val =~ m/([^\s=]+)=(\S+)/;
|
||||
die "Invalid --set-vars value: $var_val\n" unless $var && $val;
|
||||
die "Invalid --set-vars value: $var_val\n" unless $var && defined $val;
|
||||
$user_vars{$var} = {
|
||||
val => $val,
|
||||
default => 0,
|
||||
@@ -1132,7 +1132,7 @@ sub set_vars {
|
||||
%default_vars = map {
|
||||
my $var_val = $_;
|
||||
my ($var, $val) = $var_val =~ m/([^\s=]+)=(\S+)/;
|
||||
die "Invalid --set-vars value: $var_val\n" unless $var && $val;
|
||||
die "Invalid --set-vars value: $var_val\n" unless $var && defined $val;
|
||||
$var => {
|
||||
val => $val,
|
||||
default => 1,
|
||||
@@ -7690,58 +7690,63 @@ sub _iterate_dbh {
|
||||
$self->{dbs} = \@dbs;
|
||||
}
|
||||
|
||||
if ( !$self->{db} ) {
|
||||
$self->{db} = shift @{$self->{dbs}};
|
||||
PTDEBUG && _d('Next database:', $self->{db});
|
||||
return unless $self->{db};
|
||||
}
|
||||
|
||||
if ( !defined $self->{tbls} ) {
|
||||
my $sql = 'SHOW /*!50002 FULL*/ TABLES FROM ' . $q->quote($self->{db});
|
||||
PTDEBUG && _d($sql);
|
||||
my @tbls = map {
|
||||
$_->[0]; # (tbl, type)
|
||||
DATABASE:
|
||||
while ( $self->{db} || defined(my $db = shift @{$self->{dbs}}) ) {
|
||||
if ( !$self->{db} ) {
|
||||
PTDEBUG && _d('Next database:', $db);
|
||||
$self->{db} = $db;
|
||||
}
|
||||
grep {
|
||||
my ($tbl, $type) = @$_;
|
||||
(!$type || ($type ne 'VIEW'))
|
||||
&& $self->_resume_from_table($tbl)
|
||||
&& $self->table_is_allowed($self->{db}, $tbl);
|
||||
}
|
||||
@{$dbh->selectall_arrayref($sql)};
|
||||
PTDEBUG && _d('Found', scalar @tbls, 'tables in database', $self->{db});
|
||||
$self->{tbls} = \@tbls;
|
||||
}
|
||||
|
||||
while ( my $tbl = shift @{$self->{tbls}} ) {
|
||||
my $ddl = eval { $tp->get_create_table($dbh, $self->{db}, $tbl) };
|
||||
if ( my $e = $EVAL_ERROR ) {
|
||||
my $table_name = "$self->{db}.$tbl";
|
||||
if ( $e =~ /\QTable '$table_name' doesn't exist/ ) {
|
||||
PTDEBUG && _d("Skipping $table_name because it no longer exists");
|
||||
if ( !$self->{tbls} ) {
|
||||
my $sql = 'SHOW /*!50002 FULL*/ TABLES FROM ' . $q->quote($self->{db});
|
||||
PTDEBUG && _d($sql);
|
||||
my @tbls = map {
|
||||
$_->[0]; # (tbl, type)
|
||||
}
|
||||
else {
|
||||
warn "Skipping $table_name because SHOW CREATE TABLE failed: $e";
|
||||
grep {
|
||||
my ($tbl, $type) = @$_;
|
||||
(!$type || ($type ne 'VIEW'))
|
||||
&& $self->_resume_from_table($tbl)
|
||||
&& $self->table_is_allowed($self->{db}, $tbl);
|
||||
}
|
||||
next;
|
||||
@{$dbh->selectall_arrayref($sql)};
|
||||
PTDEBUG && _d('Found', scalar @tbls, 'tables in database',$self->{db});
|
||||
$self->{tbls} = \@tbls;
|
||||
}
|
||||
my $tbl_struct = $tp->parse($ddl);
|
||||
if ( $self->engine_is_allowed($tbl_struct->{engine}) ) {
|
||||
return {
|
||||
db => $self->{db},
|
||||
tbl => $tbl,
|
||||
name => $q->quote($self->{db}, $tbl),
|
||||
ddl => $ddl,
|
||||
tbl_struct => $tbl_struct,
|
||||
};
|
||||
|
||||
TABLE:
|
||||
while ( my $tbl = shift @{$self->{tbls}} ) {
|
||||
my $ddl = eval { $tp->get_create_table($dbh, $self->{db}, $tbl) };
|
||||
if ( my $e = $EVAL_ERROR ) {
|
||||
my $table_name = "$self->{db}.$tbl";
|
||||
if ( $e =~ /\QTable '$table_name' doesn't exist/ ) {
|
||||
PTDEBUG && _d("$table_name no longer exists");
|
||||
}
|
||||
else {
|
||||
warn "Skipping $table_name because SHOW CREATE TABLE failed: $e";
|
||||
}
|
||||
next TABLE;
|
||||
}
|
||||
|
||||
my $tbl_struct = $tp->parse($ddl);
|
||||
if ( $self->engine_is_allowed($tbl_struct->{engine}) ) {
|
||||
return {
|
||||
db => $self->{db},
|
||||
tbl => $tbl,
|
||||
name => $q->quote($self->{db}, $tbl),
|
||||
ddl => $ddl,
|
||||
tbl_struct => $tbl_struct,
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
PTDEBUG && _d('No more tables in database', $self->{db});
|
||||
$self->{db} = undef;
|
||||
$self->{tbls} = undef;
|
||||
PTDEBUG && _d('No more tables in database', $self->{db});
|
||||
$self->{db} = undef;
|
||||
$self->{tbls} = undef;
|
||||
} # DATABASE
|
||||
|
||||
return $self->_iterate_dbh();
|
||||
PTDEBUG && _d('No more databases');
|
||||
return;
|
||||
}
|
||||
|
||||
sub database_is_allowed {
|
||||
|
@@ -1467,7 +1467,7 @@ sub set_vars {
|
||||
if ( $user_vars ) {
|
||||
foreach my $var_val ( @$user_vars ) {
|
||||
my ($var, $val) = $var_val =~ m/([^\s=]+)=(\S+)/;
|
||||
die "Invalid --set-vars value: $var_val\n" unless $var && $val;
|
||||
die "Invalid --set-vars value: $var_val\n" unless $var && defined $val;
|
||||
$user_vars{$var} = {
|
||||
val => $val,
|
||||
default => 0,
|
||||
@@ -1481,7 +1481,7 @@ sub set_vars {
|
||||
%default_vars = map {
|
||||
my $var_val = $_;
|
||||
my ($var, $val) = $var_val =~ m/([^\s=]+)=(\S+)/;
|
||||
die "Invalid --set-vars value: $var_val\n" unless $var && $val;
|
||||
die "Invalid --set-vars value: $var_val\n" unless $var && defined $val;
|
||||
$var => {
|
||||
val => $val,
|
||||
default => 1,
|
||||
@@ -2115,8 +2115,8 @@ sub new {
|
||||
sub strip_comments {
|
||||
my ( $self, $query ) = @_;
|
||||
return unless $query;
|
||||
$query =~ s/$olc_re//go;
|
||||
$query =~ s/$mlc_re//go;
|
||||
$query =~ s/$olc_re//go;
|
||||
if ( $query =~ m/$vlc_rf/i ) { # contains show + version
|
||||
$query =~ s/$vlc_re//go;
|
||||
}
|
||||
@@ -2183,9 +2183,9 @@ sub fingerprint {
|
||||
if ( my ($beginning) = $query =~ m/\A((?:INSERT|REPLACE)(?: IGNORE)?\s+INTO.+?VALUES\s*\(.*?\))\s*,\s*\(/is ) {
|
||||
$query = $beginning; # Shorten multi-value INSERT statements ASAP
|
||||
}
|
||||
|
||||
$query =~ s/$olc_re//go;
|
||||
|
||||
$query =~ s/$mlc_re//go;
|
||||
$query =~ s/$olc_re//go;
|
||||
$query =~ s/\Ause \S+\Z/use ?/i # Abstract the DB in USE
|
||||
&& return $query;
|
||||
|
||||
|
@@ -61,7 +61,7 @@ BEGIN {
|
||||
{
|
||||
package Percona::Toolkit;
|
||||
|
||||
our $VERSION = '2.2.3';
|
||||
our $VERSION = '2.2.4';
|
||||
|
||||
use strict;
|
||||
use warnings FATAL => 'all';
|
||||
@@ -2347,7 +2347,7 @@ sub set_vars {
|
||||
if ( $user_vars ) {
|
||||
foreach my $var_val ( @$user_vars ) {
|
||||
my ($var, $val) = $var_val =~ m/([^\s=]+)=(\S+)/;
|
||||
die "Invalid --set-vars value: $var_val\n" unless $var && $val;
|
||||
die "Invalid --set-vars value: $var_val\n" unless $var && defined $val;
|
||||
$user_vars{$var} = {
|
||||
val => $val,
|
||||
default => 0,
|
||||
@@ -2361,7 +2361,7 @@ sub set_vars {
|
||||
%default_vars = map {
|
||||
my $var_val = $_;
|
||||
my ($var, $val) = $var_val =~ m/([^\s=]+)=(\S+)/;
|
||||
die "Invalid --set-vars value: $var_val\n" unless $var && $val;
|
||||
die "Invalid --set-vars value: $var_val\n" unless $var && defined $val;
|
||||
$var => {
|
||||
val => $val,
|
||||
default => 1,
|
||||
@@ -4579,8 +4579,8 @@ sub new {
|
||||
sub strip_comments {
|
||||
my ( $self, $query ) = @_;
|
||||
return unless $query;
|
||||
$query =~ s/$olc_re//go;
|
||||
$query =~ s/$mlc_re//go;
|
||||
$query =~ s/$olc_re//go;
|
||||
if ( $query =~ m/$vlc_rf/i ) { # contains show + version
|
||||
$query =~ s/$vlc_re//go;
|
||||
}
|
||||
@@ -4647,9 +4647,9 @@ sub fingerprint {
|
||||
if ( my ($beginning) = $query =~ m/\A((?:INSERT|REPLACE)(?: IGNORE)?\s+INTO.+?VALUES\s*\(.*?\))\s*,\s*\(/is ) {
|
||||
$query = $beginning; # Shorten multi-value INSERT statements ASAP
|
||||
}
|
||||
|
||||
$query =~ s/$olc_re//go;
|
||||
|
||||
$query =~ s/$mlc_re//go;
|
||||
$query =~ s/$olc_re//go;
|
||||
$query =~ s/\Ause \S+\Z/use ?/i # Abstract the DB in USE
|
||||
&& return $query;
|
||||
|
||||
@@ -10255,6 +10255,10 @@ sub identical_rows {
|
||||
|
||||
my $n_vals = $size_array1 - 1; # arrays are zero-indexed
|
||||
for my $i ( 0..$n_vals ) {
|
||||
# NULL == NULL
|
||||
# https://bugs.launchpad.net/percona-toolkit/+bug/1168434
|
||||
next if !defined $array1->[$i] && !defined $array2->[$i];
|
||||
|
||||
if ( defined $array1->[$i] && defined $array2->[$i] ) {
|
||||
return 0 unless $array1->[$i] eq $array2->[$i];
|
||||
}
|
||||
|
@@ -44,7 +44,7 @@ BEGIN {
|
||||
{
|
||||
package Percona::Toolkit;
|
||||
|
||||
our $VERSION = '2.2.3';
|
||||
our $VERSION = '2.2.4';
|
||||
|
||||
use strict;
|
||||
use warnings FATAL => 'all';
|
||||
@@ -1107,7 +1107,7 @@ sub set_vars {
|
||||
if ( $user_vars ) {
|
||||
foreach my $var_val ( @$user_vars ) {
|
||||
my ($var, $val) = $var_val =~ m/([^\s=]+)=(\S+)/;
|
||||
die "Invalid --set-vars value: $var_val\n" unless $var && $val;
|
||||
die "Invalid --set-vars value: $var_val\n" unless $var && defined $val;
|
||||
$user_vars{$var} = {
|
||||
val => $val,
|
||||
default => 0,
|
||||
@@ -1121,7 +1121,7 @@ sub set_vars {
|
||||
%default_vars = map {
|
||||
my $var_val = $_;
|
||||
my ($var, $val) = $var_val =~ m/([^\s=]+)=(\S+)/;
|
||||
die "Invalid --set-vars value: $var_val\n" unless $var && $val;
|
||||
die "Invalid --set-vars value: $var_val\n" unless $var && defined $val;
|
||||
$var => {
|
||||
val => $val,
|
||||
default => 1,
|
||||
@@ -3376,7 +3376,9 @@ sub get_rules {
|
||||
id => 'innodb_max_dirty_pages_pct',
|
||||
code => sub {
|
||||
my ( %args ) = @_;
|
||||
return _var_lt($args{variables}->{innodb_max_dirty_pages_pct}, 90);
|
||||
my $mysql_version = $args{mysql_version};
|
||||
return _var_lt($args{variables}->{innodb_max_dirty_pages_pct},
|
||||
($mysql_version < '5.5' ? 90 : 75));
|
||||
},
|
||||
},
|
||||
{
|
||||
@@ -5519,9 +5521,9 @@ flush_time seconds.
|
||||
|
||||
severity: warn
|
||||
|
||||
The key buffer size is unconfigured. In a production
|
||||
environment it should always be configured explicitly, and the default
|
||||
8MB size is not good.
|
||||
The key buffer size is set to its default value, which is not good
|
||||
for most production systems. In a production environment, key_buffer_size
|
||||
should be larger than the default 8MB size.
|
||||
|
||||
=item large_pages
|
||||
|
||||
|
@@ -1704,7 +1704,7 @@ sub set_vars {
|
||||
if ( $user_vars ) {
|
||||
foreach my $var_val ( @$user_vars ) {
|
||||
my ($var, $val) = $var_val =~ m/([^\s=]+)=(\S+)/;
|
||||
die "Invalid --set-vars value: $var_val\n" unless $var && $val;
|
||||
die "Invalid --set-vars value: $var_val\n" unless $var && defined $val;
|
||||
$user_vars{$var} = {
|
||||
val => $val,
|
||||
default => 0,
|
||||
@@ -1718,7 +1718,7 @@ sub set_vars {
|
||||
%default_vars = map {
|
||||
my $var_val = $_;
|
||||
my ($var, $val) = $var_val =~ m/([^\s=]+)=(\S+)/;
|
||||
die "Invalid --set-vars value: $var_val\n" unless $var && $val;
|
||||
die "Invalid --set-vars value: $var_val\n" unless $var && defined $val;
|
||||
$var => {
|
||||
val => $val,
|
||||
default => 1,
|
||||
|
@@ -50,7 +50,7 @@ copyright = u'2013, Percona Ireland Ltd'
|
||||
# The short X.Y version.
|
||||
version = '2.2'
|
||||
# The full version, including alpha/beta/rc tags.
|
||||
release = '2.2.3'
|
||||
release = '2.2.4'
|
||||
|
||||
# The language for content autogenerated by Sphinx. Refer to documentation
|
||||
# for a list of supported languages.
|
||||
|
@@ -562,6 +562,6 @@ Place, Suite 330, Boston, MA 02111-1307 USA.
|
||||
|
||||
=head1 VERSION
|
||||
|
||||
Percona Toolkit v2.2.3 released 2013-06-17
|
||||
Percona Toolkit v2.2.4 released 2013-07-17
|
||||
|
||||
=cut
|
||||
|
@@ -1,6 +1,52 @@
|
||||
Release Notes
|
||||
*************
|
||||
|
||||
v2.2.4 released 2013-07-17
|
||||
==========================
|
||||
|
||||
Percona Toolkit 2.2.4 has been released. This release two new features and number of bugfixes.
|
||||
|
||||
pt-query-digest --output json includes query examples as of v2.2.3. Some people might not want this because it exposes real data. New option, --output json-anon, has been implemented. This option will provide the same data without query examples. It's "anonymous" in the sense that there's no identifying data; nothing more than schema and table structs can be inferred from fingerprints.
|
||||
|
||||
When using drop swap with pt-online-schema-change there is some production impact. This impact can be measured because tool outputs the current timestamp on lines for operations that may take awhile.
|
||||
|
||||
* Fixed bug #1163735: pt-table-checksum fails if explicit_defaults_for_timestamp is enabled in 5.6
|
||||
pt-table-checksum would fail if variable explicit_defaults_for_timestamp was enabled in MySQL 5.6.
|
||||
|
||||
* Fixed bug #1182856: Zero values causes "Invalid --set-vars value: var=0"
|
||||
Trying to assign 0 to any variable by using --set-vars option would cause “Invalid --set-vars value” message.
|
||||
|
||||
* Fixed bug #1188264: pt-online-schema-change error copying rows: Undefined subroutine &pt_online_schema_change::get
|
||||
Fixed the typo in the pt-online-schema-change code that could lead to a tool crash when copying the rows.
|
||||
|
||||
* Fixed bug #1199591: pt-table-checksum doesn't use non-unique index with highest cardinality
|
||||
pt-table-checksum was using the first non-unique index instead of the one with the highest cardinality due to a sorting bug.
|
||||
|
||||
Percona Toolkit packages can be downloaded from
|
||||
http://www.percona.com/downloads/percona-toolkit/ or the Percona Software
|
||||
Repositories (http://www.percona.com/software/repositories
|
||||
|
||||
Changelog
|
||||
---------
|
||||
|
||||
* Added pt-query-digest anonymous JSON output
|
||||
* Added pt-online-schema-change timestamp output
|
||||
* Fixed bug #1136559: pt-table-checksum: Deep recursion on subroutine "SchemaIterator::_iterate_dbh"
|
||||
* Fixed bug #1163735: pt-table-checksum fails if explicit_defaults_for_timestamp is enabled in 5.6
|
||||
* Fixed bug #1182856: Zero values causes "Invalid --set-vars value: var=0"
|
||||
* Fixed bug #1188264: pt-online-schema-change error copying rows: Undefined subroutine &pt_online_schema_change::get
|
||||
* Fixed bug #1195034: pt-deadlock-logger error: Use of uninitialized value $ts in pattern match (m//)
|
||||
* Fixed bug #1199591: pt-table-checksum doesn't use non-unique index with highest cardinality
|
||||
* Fixed bug #1168434: pt-upgrade reports differences on NULL
|
||||
* Fixed bug #1172317: pt-sift does not work if pt-stalk did not collect due to a full disk
|
||||
* Fixed bug #1176010: pt-query-digest doesn't group db and `db` together
|
||||
* Fixed bug #1137556: pt-heartbeat docs don't account for --utc
|
||||
* Fixed bug #1168106: pt-variable-advisor has the wrong default value for innodb_max_dirty_pages_pct in 5.5 and 5.6
|
||||
* Fixed bug #1168110: pt-variable-advisor shows key_buffer_size in 5.6 as unconfigured (even though it is)
|
||||
* Fixed bug #1171968: pt-query-digest docs don't mention --type=rawlog
|
||||
* Fixed bug #1174956: pt-query-digest and pt-fingerprint don't strip some multi-line comments
|
||||
|
||||
|
||||
v2.2.3 released 2013-06-17
|
||||
==========================
|
||||
|
||||
|
@@ -228,10 +228,12 @@ override query_report => sub {
|
||||
distillate => $distill,
|
||||
attribute => $groupby,
|
||||
query_count => $times_seen,
|
||||
example => {
|
||||
query => substr($sample->{arg}, 0, $self->max_query_length),
|
||||
ts => $sample->{ts} ? parse_timestamp($sample->{ts}) : undef,
|
||||
},
|
||||
$args{anon} ? () : (
|
||||
example => {
|
||||
query => substr($sample->{arg}, 0, $self->max_query_length),
|
||||
ts => $sample->{ts} ? parse_timestamp($sample->{ts}) : undef,
|
||||
},
|
||||
),
|
||||
};
|
||||
|
||||
my %metrics;
|
||||
@@ -340,26 +342,28 @@ override query_report => sub {
|
||||
push @tables, { status => $status, create => $create };
|
||||
}
|
||||
|
||||
# Convert possible non-SELECTs for EXPLAIN.
|
||||
if ( $item =~ m/^(?:[\(\s]*select|insert|replace)/ ) {
|
||||
if ( $item =~ m/^(?:insert|replace)/ ) {
|
||||
# Cannot convert or EXPLAIN INSERT or REPLACE queries.
|
||||
if ( !$args{anon} ) {
|
||||
# Convert possible non-SELECTs for EXPLAIN.
|
||||
if ( $item =~ m/^(?:[\(\s]*select|insert|replace)/ ) {
|
||||
if ( $item =~ m/^(?:insert|replace)/ ) {
|
||||
# Cannot convert or EXPLAIN INSERT or REPLACE queries.
|
||||
}
|
||||
else {
|
||||
# SELECT queries don't need to converted for EXPLAIN.
|
||||
|
||||
# TODO: return the actual EXPLAIN plan
|
||||
# $self->explain_report($query, $vals->{default_db});
|
||||
}
|
||||
}
|
||||
else {
|
||||
# SELECT queries don't need to converted for EXPLAIN.
|
||||
|
||||
# TODO: return the actual EXPLAIN plan
|
||||
# $self->explain_report($query, $vals->{default_db});
|
||||
}
|
||||
}
|
||||
else {
|
||||
# Query is not SELECT, INSERT, or REPLACE, so we can convert
|
||||
# it for EXPLAIN.
|
||||
my $converted = $qr->convert_to_select(
|
||||
$sample->{arg} || '',
|
||||
);
|
||||
if ( $converted && $converted =~ m/^[\(\s]*select/i ) {
|
||||
$class->{example}->{as_select} = $converted;
|
||||
# Query is not SELECT, INSERT, or REPLACE, so we can convert
|
||||
# it for EXPLAIN.
|
||||
my $converted = $qr->convert_to_select(
|
||||
$sample->{arg} || '',
|
||||
);
|
||||
if ( $converted && $converted =~ m/^[\(\s]*select/i ) {
|
||||
$class->{example}->{as_select} = $converted;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -554,7 +554,7 @@ sub _find_best_index {
|
||||
@possible_indexes = sort {
|
||||
# Prefer the index with the highest cardinality.
|
||||
my $cmp
|
||||
= $indexes->{$b}->{cardinality} <=> $indexes->{$b}->{cardinality};
|
||||
= $indexes->{$b}->{cardinality} <=> $indexes->{$a}->{cardinality};
|
||||
if ( $cmp == 0 ) {
|
||||
# Indexes have the same cardinality; prefer the one with
|
||||
# more columns.
|
||||
|
@@ -1289,7 +1289,7 @@ sub set_vars {
|
||||
if ( $user_vars ) {
|
||||
foreach my $var_val ( @$user_vars ) {
|
||||
my ($var, $val) = $var_val =~ m/([^\s=]+)=(\S+)/;
|
||||
die "Invalid --set-vars value: $var_val\n" unless $var && $val;
|
||||
die "Invalid --set-vars value: $var_val\n" unless $var && defined $val;
|
||||
$user_vars{$var} = {
|
||||
val => $val,
|
||||
default => 0,
|
||||
@@ -1303,7 +1303,7 @@ sub set_vars {
|
||||
%default_vars = map {
|
||||
my $var_val = $_;
|
||||
my ($var, $val) = $var_val =~ m/([^\s=]+)=(\S+)/;
|
||||
die "Invalid --set-vars value: $var_val\n" unless $var && $val;
|
||||
die "Invalid --set-vars value: $var_val\n" unless $var && defined $val;
|
||||
$var => {
|
||||
val => $val,
|
||||
default => 1,
|
||||
|
@@ -19,7 +19,7 @@
|
||||
# ###########################################################################
|
||||
package Percona::Toolkit;
|
||||
|
||||
our $VERSION = '2.2.3';
|
||||
our $VERSION = '2.2.4';
|
||||
|
||||
use strict;
|
||||
use warnings FATAL => 'all';
|
||||
|
@@ -62,8 +62,8 @@ sub new {
|
||||
sub strip_comments {
|
||||
my ( $self, $query ) = @_;
|
||||
return unless $query;
|
||||
$query =~ s/$olc_re//go;
|
||||
$query =~ s/$mlc_re//go;
|
||||
$query =~ s/$olc_re//go;
|
||||
if ( $query =~ m/$vlc_rf/i ) { # contains show + version
|
||||
$query =~ s/$vlc_re//go;
|
||||
}
|
||||
@@ -166,9 +166,9 @@ sub fingerprint {
|
||||
if ( my ($beginning) = $query =~ m/\A((?:INSERT|REPLACE)(?: IGNORE)?\s+INTO.+?VALUES\s*\(.*?\))\s*,\s*\(/is ) {
|
||||
$query = $beginning; # Shorten multi-value INSERT statements ASAP
|
||||
}
|
||||
|
||||
$query =~ s/$olc_re//go;
|
||||
|
||||
$query =~ s/$mlc_re//go;
|
||||
$query =~ s/$olc_re//go;
|
||||
$query =~ s/\Ause \S+\Z/use ?/i # Abstract the DB in USE
|
||||
&& return $query;
|
||||
|
||||
|
@@ -334,64 +334,67 @@ sub _iterate_dbh {
|
||||
$self->{dbs} = \@dbs;
|
||||
}
|
||||
|
||||
if ( !$self->{db} ) {
|
||||
$self->{db} = shift @{$self->{dbs}};
|
||||
PTDEBUG && _d('Next database:', $self->{db});
|
||||
return unless $self->{db};
|
||||
}
|
||||
|
||||
if ( !defined $self->{tbls} ) {
|
||||
my $sql = 'SHOW /*!50002 FULL*/ TABLES FROM ' . $q->quote($self->{db});
|
||||
PTDEBUG && _d($sql);
|
||||
my @tbls = map {
|
||||
$_->[0]; # (tbl, type)
|
||||
DATABASE:
|
||||
while ( $self->{db} || defined(my $db = shift @{$self->{dbs}}) ) {
|
||||
if ( !$self->{db} ) {
|
||||
PTDEBUG && _d('Next database:', $db);
|
||||
$self->{db} = $db;
|
||||
}
|
||||
grep {
|
||||
my ($tbl, $type) = @$_;
|
||||
(!$type || ($type ne 'VIEW'))
|
||||
&& $self->_resume_from_table($tbl)
|
||||
&& $self->table_is_allowed($self->{db}, $tbl);
|
||||
}
|
||||
@{$dbh->selectall_arrayref($sql)};
|
||||
PTDEBUG && _d('Found', scalar @tbls, 'tables in database', $self->{db});
|
||||
$self->{tbls} = \@tbls;
|
||||
}
|
||||
|
||||
while ( my $tbl = shift @{$self->{tbls}} ) {
|
||||
my $ddl = eval { $tp->get_create_table($dbh, $self->{db}, $tbl) };
|
||||
if ( my $e = $EVAL_ERROR ) {
|
||||
my $table_name = "$self->{db}.$tbl";
|
||||
# SHOW CREATE TABLE failed. This is a bit puzzling;
|
||||
# maybe the table got dropped, or crashed. Not much we can
|
||||
# do about it; If the table is missing, just PTDEBUG it, but
|
||||
# otherwise, warn with the error.
|
||||
if ( $e =~ /\QTable '$table_name' doesn't exist/ ) {
|
||||
PTDEBUG && _d("Skipping $table_name because it no longer exists");
|
||||
if ( !$self->{tbls} ) {
|
||||
my $sql = 'SHOW /*!50002 FULL*/ TABLES FROM ' . $q->quote($self->{db});
|
||||
PTDEBUG && _d($sql);
|
||||
my @tbls = map {
|
||||
$_->[0]; # (tbl, type)
|
||||
}
|
||||
else {
|
||||
warn "Skipping $table_name because SHOW CREATE TABLE failed: $e";
|
||||
grep {
|
||||
my ($tbl, $type) = @$_;
|
||||
(!$type || ($type ne 'VIEW'))
|
||||
&& $self->_resume_from_table($tbl)
|
||||
&& $self->table_is_allowed($self->{db}, $tbl);
|
||||
}
|
||||
next;
|
||||
@{$dbh->selectall_arrayref($sql)};
|
||||
PTDEBUG && _d('Found', scalar @tbls, 'tables in database',$self->{db});
|
||||
$self->{tbls} = \@tbls;
|
||||
}
|
||||
my $tbl_struct = $tp->parse($ddl);
|
||||
if ( $self->engine_is_allowed($tbl_struct->{engine}) ) {
|
||||
return {
|
||||
db => $self->{db},
|
||||
tbl => $tbl,
|
||||
name => $q->quote($self->{db}, $tbl),
|
||||
ddl => $ddl,
|
||||
tbl_struct => $tbl_struct,
|
||||
};
|
||||
|
||||
TABLE:
|
||||
while ( my $tbl = shift @{$self->{tbls}} ) {
|
||||
my $ddl = eval { $tp->get_create_table($dbh, $self->{db}, $tbl) };
|
||||
if ( my $e = $EVAL_ERROR ) {
|
||||
my $table_name = "$self->{db}.$tbl";
|
||||
# SHOW CREATE TABLE failed. This is a bit puzzling;
|
||||
# maybe the table got dropped, or crashed. Not much we can
|
||||
# do about it; If the table is missing, just PTDEBUG it, but
|
||||
# otherwise, warn with the error.
|
||||
if ( $e =~ /\QTable '$table_name' doesn't exist/ ) {
|
||||
PTDEBUG && _d("$table_name no longer exists");
|
||||
}
|
||||
else {
|
||||
warn "Skipping $table_name because SHOW CREATE TABLE failed: $e";
|
||||
}
|
||||
next TABLE;
|
||||
}
|
||||
|
||||
my $tbl_struct = $tp->parse($ddl);
|
||||
if ( $self->engine_is_allowed($tbl_struct->{engine}) ) {
|
||||
return {
|
||||
db => $self->{db},
|
||||
tbl => $tbl,
|
||||
name => $q->quote($self->{db}, $tbl),
|
||||
ddl => $ddl,
|
||||
tbl_struct => $tbl_struct,
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
PTDEBUG && _d('No more tables in database', $self->{db});
|
||||
$self->{db} = undef;
|
||||
$self->{tbls} = undef;
|
||||
PTDEBUG && _d('No more tables in database', $self->{db});
|
||||
$self->{db} = undef;
|
||||
$self->{tbls} = undef;
|
||||
} # DATABASE
|
||||
|
||||
# Recurse to get the next database. If there's no next db, then the
|
||||
# call will return undef and we'll return undef, too.
|
||||
return $self->_iterate_dbh();
|
||||
PTDEBUG && _d('No more databases');
|
||||
return;
|
||||
}
|
||||
|
||||
sub database_is_allowed {
|
||||
|
@@ -214,7 +214,9 @@ sub get_rules {
|
||||
id => 'innodb_max_dirty_pages_pct',
|
||||
code => sub {
|
||||
my ( %args ) = @_;
|
||||
return _var_lt($args{variables}->{innodb_max_dirty_pages_pct}, 90);
|
||||
my $mysql_version = $args{mysql_version};
|
||||
return _var_lt($args{variables}->{innodb_max_dirty_pages_pct},
|
||||
($mysql_version < '5.5' ? 90 : 75));
|
||||
},
|
||||
},
|
||||
{
|
||||
|
@@ -113,6 +113,10 @@ make_sandbox() {
|
||||
echo "query_cache_size=$QUERY_CACHE_SIZE" >> /tmp/$port/my.sandbox.cnf
|
||||
fi
|
||||
|
||||
if [ -n "$EXTRA_DEFAULTS_FILE" ]; then
|
||||
cat "$EXTRA_DEFAULTS_FILE" >> /tmp/$port/my.sandbox.cnf
|
||||
fi
|
||||
|
||||
# If the sandbox is a slave, set it read_only.
|
||||
if [ "$type" = "slave" ]; then
|
||||
echo "read_only" >> /tmp/$port/my.sandbox.cnf
|
||||
|
@@ -38,9 +38,6 @@ my $dbh = $sb->get_dbh_for('master');
|
||||
if ( !$dbh ) {
|
||||
plan skip_all => 'Cannot connect to sandbox master';
|
||||
}
|
||||
else {
|
||||
plan tests => 54;
|
||||
}
|
||||
|
||||
my $q = new Quoter();
|
||||
my $tp = new TableParser(Quoter=>$q);
|
||||
@@ -831,6 +828,26 @@ is_deeply(
|
||||
"Bug 995274: nibble iter works"
|
||||
);
|
||||
|
||||
|
||||
# #############################################################################
|
||||
# pt-table-checksum doesn't use non-unique index with highest cardinality
|
||||
# https://bugs.launchpad.net/percona-toolkit/+bug/1199591
|
||||
# #############################################################################
|
||||
|
||||
diag(`/tmp/12345/use < $trunk/t/lib/samples/cardinality.sql >/dev/null`);
|
||||
|
||||
$ni = make_nibble_iter(
|
||||
db => 'cardb',
|
||||
tbl => 't',
|
||||
argv => [qw(--databases cardb --chunk-size 2)],
|
||||
);
|
||||
|
||||
is(
|
||||
$ni->{index},
|
||||
'b',
|
||||
"Use non-unique index with highest cardinality (bug 1199591)"
|
||||
);
|
||||
|
||||
# #############################################################################
|
||||
# Done.
|
||||
# #############################################################################
|
||||
@@ -846,4 +863,4 @@ like(
|
||||
);
|
||||
$sb->wipe_clean($dbh);
|
||||
ok($sb->ok(), "Sandbox servers") or BAIL_OUT(__FILE__ . " broke the sandbox");
|
||||
exit;
|
||||
done_testing;
|
||||
|
@@ -2021,6 +2021,48 @@ is(
|
||||
"Non-zero exit status on error parsing options (bug 1039074)"
|
||||
);
|
||||
|
||||
|
||||
# #############################################################################
|
||||
# --set-vars/set_vars()
|
||||
# #############################################################################
|
||||
|
||||
@ARGV = qw();
|
||||
$o = new OptionParser(file => "$trunk/bin/pt-archiver");
|
||||
$o->get_specs();
|
||||
$o->get_opts();
|
||||
|
||||
my $vars = $o->set_vars("$trunk/bin/pt-archiver");
|
||||
is_deeply(
|
||||
$vars,
|
||||
{
|
||||
wait_timeout => {
|
||||
default => 1,
|
||||
val => '10000',
|
||||
},
|
||||
},
|
||||
"set_vars(): 1 default from docs"
|
||||
) or diag(Dumper($vars));
|
||||
|
||||
# Bug 1182856: Zero values causes "Invalid --set-vars value: var=0"
|
||||
@ARGV = qw(--set-vars SQL_LOG_BIN=0);
|
||||
$o->get_opts();
|
||||
|
||||
$vars = $o->set_vars("$trunk/bin/pt-archiver");
|
||||
is_deeply(
|
||||
$vars,
|
||||
{
|
||||
wait_timeout => {
|
||||
default => 1,
|
||||
val => '10000',
|
||||
},
|
||||
SQL_LOG_BIN => {
|
||||
default => 0,
|
||||
val => '0',
|
||||
},
|
||||
},
|
||||
"set_vars(): var=0 (bug 1182856)"
|
||||
) or diag(Dumper($vars));
|
||||
|
||||
# #############################################################################
|
||||
# Done.
|
||||
# #############################################################################
|
||||
|
@@ -10,7 +10,7 @@ BEGIN {
|
||||
use strict;
|
||||
use warnings FATAL => 'all';
|
||||
use English qw(-no_match_vars);
|
||||
use Test::More tests => 271;
|
||||
use Test::More;
|
||||
|
||||
use QueryRewriter;
|
||||
use QueryParser;
|
||||
@@ -407,6 +407,15 @@ is(
|
||||
"Fingerprint db.tbl<number>name (preserve number)"
|
||||
);
|
||||
|
||||
|
||||
is(
|
||||
$qr->fingerprint(
|
||||
"/* -- S++ SU ABORTABLE -- spd_user: rspadim */SELECT SQL_SMALL_RESULT SQL_CACHE DISTINCT centro_atividade FROM est_dia WHERE unidade_id=1001 AND item_id=67 AND item_id_red=573"
|
||||
),
|
||||
"select sql_small_result sql_cache distinct centro_atividade from est_dia where unidade_id=? and item_id=? and item_id_red=?",
|
||||
"Fingerprint /* -- comment */ SELECT (bug 1174956)"
|
||||
);
|
||||
|
||||
# #############################################################################
|
||||
# convert_to_select()
|
||||
# #############################################################################
|
||||
@@ -1406,4 +1415,4 @@ is(
|
||||
# #############################################################################
|
||||
# Done.
|
||||
# #############################################################################
|
||||
exit;
|
||||
done_testing;
|
||||
|
@@ -547,10 +547,24 @@ eval {
|
||||
|
||||
diag(`$trunk/sandbox/stop-sandbox $master3_port >/dev/null`);
|
||||
|
||||
# #############################################################################
|
||||
# Bug 1136559: Deep recursion on subroutine "SchemaIterator::_iterate_dbh"
|
||||
# #############################################################################
|
||||
|
||||
$sb->wipe_clean($dbh);
|
||||
diag(`/tmp/12345/use < $trunk/t/lib/samples/100-dbs.sql`);
|
||||
|
||||
test_so(
|
||||
filters => [],
|
||||
result => "foo001.bar001 ",
|
||||
lives_ok => 1,
|
||||
test_name => "Bug 1136559: Deep recursion on subroutine SchemaIterator::_iterate_dbh",
|
||||
);
|
||||
|
||||
diag(`/tmp/12345/use < $trunk/t/lib/samples/100-dbs-drop.sql`);
|
||||
|
||||
# #############################################################################
|
||||
# Done.
|
||||
# #############################################################################
|
||||
ok($sb->ok(), "Sandbox servers") or BAIL_OUT(__FILE__ . " broke the sandbox");
|
||||
|
||||
done_testing;
|
||||
exit;
|
||||
|
100
t/lib/samples/100-dbs-drop.sql
Normal file
100
t/lib/samples/100-dbs-drop.sql
Normal file
@@ -0,0 +1,100 @@
|
||||
DROP DATABASE IF EXISTS foo001;
|
||||
DROP DATABASE IF EXISTS foo002;
|
||||
DROP DATABASE IF EXISTS foo003;
|
||||
DROP DATABASE IF EXISTS foo004;
|
||||
DROP DATABASE IF EXISTS foo005;
|
||||
DROP DATABASE IF EXISTS foo006;
|
||||
DROP DATABASE IF EXISTS foo007;
|
||||
DROP DATABASE IF EXISTS foo008;
|
||||
DROP DATABASE IF EXISTS foo009;
|
||||
DROP DATABASE IF EXISTS foo010;
|
||||
DROP DATABASE IF EXISTS foo011;
|
||||
DROP DATABASE IF EXISTS foo012;
|
||||
DROP DATABASE IF EXISTS foo013;
|
||||
DROP DATABASE IF EXISTS foo014;
|
||||
DROP DATABASE IF EXISTS foo015;
|
||||
DROP DATABASE IF EXISTS foo016;
|
||||
DROP DATABASE IF EXISTS foo017;
|
||||
DROP DATABASE IF EXISTS foo018;
|
||||
DROP DATABASE IF EXISTS foo019;
|
||||
DROP DATABASE IF EXISTS foo020;
|
||||
DROP DATABASE IF EXISTS foo021;
|
||||
DROP DATABASE IF EXISTS foo022;
|
||||
DROP DATABASE IF EXISTS foo023;
|
||||
DROP DATABASE IF EXISTS foo024;
|
||||
DROP DATABASE IF EXISTS foo025;
|
||||
DROP DATABASE IF EXISTS foo026;
|
||||
DROP DATABASE IF EXISTS foo027;
|
||||
DROP DATABASE IF EXISTS foo028;
|
||||
DROP DATABASE IF EXISTS foo029;
|
||||
DROP DATABASE IF EXISTS foo030;
|
||||
DROP DATABASE IF EXISTS foo031;
|
||||
DROP DATABASE IF EXISTS foo032;
|
||||
DROP DATABASE IF EXISTS foo033;
|
||||
DROP DATABASE IF EXISTS foo034;
|
||||
DROP DATABASE IF EXISTS foo035;
|
||||
DROP DATABASE IF EXISTS foo036;
|
||||
DROP DATABASE IF EXISTS foo037;
|
||||
DROP DATABASE IF EXISTS foo038;
|
||||
DROP DATABASE IF EXISTS foo039;
|
||||
DROP DATABASE IF EXISTS foo040;
|
||||
DROP DATABASE IF EXISTS foo041;
|
||||
DROP DATABASE IF EXISTS foo042;
|
||||
DROP DATABASE IF EXISTS foo043;
|
||||
DROP DATABASE IF EXISTS foo044;
|
||||
DROP DATABASE IF EXISTS foo045;
|
||||
DROP DATABASE IF EXISTS foo046;
|
||||
DROP DATABASE IF EXISTS foo047;
|
||||
DROP DATABASE IF EXISTS foo048;
|
||||
DROP DATABASE IF EXISTS foo049;
|
||||
DROP DATABASE IF EXISTS foo050;
|
||||
DROP DATABASE IF EXISTS foo051;
|
||||
DROP DATABASE IF EXISTS foo052;
|
||||
DROP DATABASE IF EXISTS foo053;
|
||||
DROP DATABASE IF EXISTS foo054;
|
||||
DROP DATABASE IF EXISTS foo055;
|
||||
DROP DATABASE IF EXISTS foo056;
|
||||
DROP DATABASE IF EXISTS foo057;
|
||||
DROP DATABASE IF EXISTS foo058;
|
||||
DROP DATABASE IF EXISTS foo059;
|
||||
DROP DATABASE IF EXISTS foo060;
|
||||
DROP DATABASE IF EXISTS foo061;
|
||||
DROP DATABASE IF EXISTS foo062;
|
||||
DROP DATABASE IF EXISTS foo063;
|
||||
DROP DATABASE IF EXISTS foo064;
|
||||
DROP DATABASE IF EXISTS foo065;
|
||||
DROP DATABASE IF EXISTS foo066;
|
||||
DROP DATABASE IF EXISTS foo067;
|
||||
DROP DATABASE IF EXISTS foo068;
|
||||
DROP DATABASE IF EXISTS foo069;
|
||||
DROP DATABASE IF EXISTS foo070;
|
||||
DROP DATABASE IF EXISTS foo071;
|
||||
DROP DATABASE IF EXISTS foo072;
|
||||
DROP DATABASE IF EXISTS foo073;
|
||||
DROP DATABASE IF EXISTS foo074;
|
||||
DROP DATABASE IF EXISTS foo075;
|
||||
DROP DATABASE IF EXISTS foo076;
|
||||
DROP DATABASE IF EXISTS foo077;
|
||||
DROP DATABASE IF EXISTS foo078;
|
||||
DROP DATABASE IF EXISTS foo079;
|
||||
DROP DATABASE IF EXISTS foo080;
|
||||
DROP DATABASE IF EXISTS foo081;
|
||||
DROP DATABASE IF EXISTS foo082;
|
||||
DROP DATABASE IF EXISTS foo083;
|
||||
DROP DATABASE IF EXISTS foo084;
|
||||
DROP DATABASE IF EXISTS foo085;
|
||||
DROP DATABASE IF EXISTS foo086;
|
||||
DROP DATABASE IF EXISTS foo087;
|
||||
DROP DATABASE IF EXISTS foo088;
|
||||
DROP DATABASE IF EXISTS foo089;
|
||||
DROP DATABASE IF EXISTS foo090;
|
||||
DROP DATABASE IF EXISTS foo091;
|
||||
DROP DATABASE IF EXISTS foo092;
|
||||
DROP DATABASE IF EXISTS foo093;
|
||||
DROP DATABASE IF EXISTS foo094;
|
||||
DROP DATABASE IF EXISTS foo095;
|
||||
DROP DATABASE IF EXISTS foo096;
|
||||
DROP DATABASE IF EXISTS foo097;
|
||||
DROP DATABASE IF EXISTS foo098;
|
||||
DROP DATABASE IF EXISTS foo099;
|
||||
DROP DATABASE IF EXISTS foo100;
|
105
t/lib/samples/100-dbs.sql
Normal file
105
t/lib/samples/100-dbs.sql
Normal file
@@ -0,0 +1,105 @@
|
||||
CREATE DATABASE IF NOT EXISTS foo001;
|
||||
CREATE DATABASE IF NOT EXISTS foo002;
|
||||
CREATE DATABASE IF NOT EXISTS foo003;
|
||||
CREATE DATABASE IF NOT EXISTS foo004;
|
||||
CREATE DATABASE IF NOT EXISTS foo005;
|
||||
CREATE DATABASE IF NOT EXISTS foo006;
|
||||
CREATE DATABASE IF NOT EXISTS foo007;
|
||||
CREATE DATABASE IF NOT EXISTS foo008;
|
||||
CREATE DATABASE IF NOT EXISTS foo009;
|
||||
CREATE DATABASE IF NOT EXISTS foo010;
|
||||
CREATE DATABASE IF NOT EXISTS foo011;
|
||||
CREATE DATABASE IF NOT EXISTS foo012;
|
||||
CREATE DATABASE IF NOT EXISTS foo013;
|
||||
CREATE DATABASE IF NOT EXISTS foo014;
|
||||
CREATE DATABASE IF NOT EXISTS foo015;
|
||||
CREATE DATABASE IF NOT EXISTS foo016;
|
||||
CREATE DATABASE IF NOT EXISTS foo017;
|
||||
CREATE DATABASE IF NOT EXISTS foo018;
|
||||
CREATE DATABASE IF NOT EXISTS foo019;
|
||||
CREATE DATABASE IF NOT EXISTS foo020;
|
||||
CREATE DATABASE IF NOT EXISTS foo021;
|
||||
CREATE DATABASE IF NOT EXISTS foo022;
|
||||
CREATE DATABASE IF NOT EXISTS foo023;
|
||||
CREATE DATABASE IF NOT EXISTS foo024;
|
||||
CREATE DATABASE IF NOT EXISTS foo025;
|
||||
CREATE DATABASE IF NOT EXISTS foo026;
|
||||
CREATE DATABASE IF NOT EXISTS foo027;
|
||||
CREATE DATABASE IF NOT EXISTS foo028;
|
||||
CREATE DATABASE IF NOT EXISTS foo029;
|
||||
CREATE DATABASE IF NOT EXISTS foo030;
|
||||
CREATE DATABASE IF NOT EXISTS foo031;
|
||||
CREATE DATABASE IF NOT EXISTS foo032;
|
||||
CREATE DATABASE IF NOT EXISTS foo033;
|
||||
CREATE DATABASE IF NOT EXISTS foo034;
|
||||
CREATE DATABASE IF NOT EXISTS foo035;
|
||||
CREATE DATABASE IF NOT EXISTS foo036;
|
||||
CREATE DATABASE IF NOT EXISTS foo037;
|
||||
CREATE DATABASE IF NOT EXISTS foo038;
|
||||
CREATE DATABASE IF NOT EXISTS foo039;
|
||||
CREATE DATABASE IF NOT EXISTS foo040;
|
||||
CREATE DATABASE IF NOT EXISTS foo041;
|
||||
CREATE DATABASE IF NOT EXISTS foo042;
|
||||
CREATE DATABASE IF NOT EXISTS foo043;
|
||||
CREATE DATABASE IF NOT EXISTS foo044;
|
||||
CREATE DATABASE IF NOT EXISTS foo045;
|
||||
CREATE DATABASE IF NOT EXISTS foo046;
|
||||
CREATE DATABASE IF NOT EXISTS foo047;
|
||||
CREATE DATABASE IF NOT EXISTS foo048;
|
||||
CREATE DATABASE IF NOT EXISTS foo049;
|
||||
CREATE DATABASE IF NOT EXISTS foo050;
|
||||
CREATE DATABASE IF NOT EXISTS foo051;
|
||||
CREATE DATABASE IF NOT EXISTS foo052;
|
||||
CREATE DATABASE IF NOT EXISTS foo053;
|
||||
CREATE DATABASE IF NOT EXISTS foo054;
|
||||
CREATE DATABASE IF NOT EXISTS foo055;
|
||||
CREATE DATABASE IF NOT EXISTS foo056;
|
||||
CREATE DATABASE IF NOT EXISTS foo057;
|
||||
CREATE DATABASE IF NOT EXISTS foo058;
|
||||
CREATE DATABASE IF NOT EXISTS foo059;
|
||||
CREATE DATABASE IF NOT EXISTS foo060;
|
||||
CREATE DATABASE IF NOT EXISTS foo061;
|
||||
CREATE DATABASE IF NOT EXISTS foo062;
|
||||
CREATE DATABASE IF NOT EXISTS foo063;
|
||||
CREATE DATABASE IF NOT EXISTS foo064;
|
||||
CREATE DATABASE IF NOT EXISTS foo065;
|
||||
CREATE DATABASE IF NOT EXISTS foo066;
|
||||
CREATE DATABASE IF NOT EXISTS foo067;
|
||||
CREATE DATABASE IF NOT EXISTS foo068;
|
||||
CREATE DATABASE IF NOT EXISTS foo069;
|
||||
CREATE DATABASE IF NOT EXISTS foo070;
|
||||
CREATE DATABASE IF NOT EXISTS foo071;
|
||||
CREATE DATABASE IF NOT EXISTS foo072;
|
||||
CREATE DATABASE IF NOT EXISTS foo073;
|
||||
CREATE DATABASE IF NOT EXISTS foo074;
|
||||
CREATE DATABASE IF NOT EXISTS foo075;
|
||||
CREATE DATABASE IF NOT EXISTS foo076;
|
||||
CREATE DATABASE IF NOT EXISTS foo077;
|
||||
CREATE DATABASE IF NOT EXISTS foo078;
|
||||
CREATE DATABASE IF NOT EXISTS foo079;
|
||||
CREATE DATABASE IF NOT EXISTS foo080;
|
||||
CREATE DATABASE IF NOT EXISTS foo081;
|
||||
CREATE DATABASE IF NOT EXISTS foo082;
|
||||
CREATE DATABASE IF NOT EXISTS foo083;
|
||||
CREATE DATABASE IF NOT EXISTS foo084;
|
||||
CREATE DATABASE IF NOT EXISTS foo085;
|
||||
CREATE DATABASE IF NOT EXISTS foo086;
|
||||
CREATE DATABASE IF NOT EXISTS foo087;
|
||||
CREATE DATABASE IF NOT EXISTS foo088;
|
||||
CREATE DATABASE IF NOT EXISTS foo089;
|
||||
CREATE DATABASE IF NOT EXISTS foo090;
|
||||
CREATE DATABASE IF NOT EXISTS foo091;
|
||||
CREATE DATABASE IF NOT EXISTS foo092;
|
||||
CREATE DATABASE IF NOT EXISTS foo093;
|
||||
CREATE DATABASE IF NOT EXISTS foo094;
|
||||
CREATE DATABASE IF NOT EXISTS foo095;
|
||||
CREATE DATABASE IF NOT EXISTS foo096;
|
||||
CREATE DATABASE IF NOT EXISTS foo097;
|
||||
CREATE DATABASE IF NOT EXISTS foo098;
|
||||
CREATE DATABASE IF NOT EXISTS foo099;
|
||||
CREATE DATABASE IF NOT EXISTS foo100;
|
||||
CREATE TABLE IF NOT EXISTS foo001.bar001 (
|
||||
`id` int unsigned NOT NULL AUTO_INCREMENT,
|
||||
`value` varchar(255) NOT NULL,
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
49
t/lib/samples/cardinality.sql
Normal file
49
t/lib/samples/cardinality.sql
Normal file
@@ -0,0 +1,49 @@
|
||||
DROP DATABASE IF EXISTS cardb;
|
||||
CREATE DATABASE cardb;
|
||||
USE cardb;
|
||||
CREATE TABLE t (
|
||||
high INT UNSIGNED NOT NULL,
|
||||
low INT UNSIGNED NOT NULL,
|
||||
INDEX a (low),
|
||||
INDEX b (high),
|
||||
INDEX c (low)
|
||||
) ENGINE=InnoDB;
|
||||
INSERT INTO t VALUES
|
||||
(1, 1),
|
||||
(2, 1),
|
||||
(3, 1),
|
||||
(4, 1),
|
||||
(5, 1),
|
||||
(6, 1),
|
||||
(7, 1),
|
||||
(8, 1),
|
||||
(9, 1),
|
||||
(10, 1),
|
||||
(11, 1),
|
||||
(12, 1),
|
||||
(13, 1),
|
||||
(14, 1),
|
||||
(15, 1),
|
||||
(16, 1),
|
||||
(17, 1),
|
||||
(18, 1),
|
||||
(19, 1),
|
||||
(20, 1),
|
||||
(21, 2),
|
||||
(22, 2),
|
||||
(23, 2),
|
||||
(24, 2),
|
||||
(25, 2),
|
||||
(26, 2),
|
||||
(27, 2),
|
||||
(28, 2),
|
||||
(29, 2),
|
||||
(30, 2),
|
||||
(31, 2),
|
||||
(32, 2),
|
||||
(33, 2),
|
||||
(34, 2),
|
||||
(35, 2),
|
||||
(36, 2),
|
||||
(37, 2);
|
||||
ANALYZE TABLE t;
|
File diff suppressed because it is too large
Load Diff
@@ -15,6 +15,8 @@ use PerconaTest;
|
||||
use Sandbox;
|
||||
require "$trunk/bin/pt-deadlock-logger";
|
||||
|
||||
use Data::Dumper;
|
||||
|
||||
# #############################################################################
|
||||
# https://bugs.launchpad.net/percona-toolkit/+bug/903443
|
||||
# pt-deadlock-logger crashes on MySQL 5.5
|
||||
@@ -119,6 +121,21 @@ is_deeply(
|
||||
"Bug 1082104: pt-deadlock-logger shows host as user when the username has a dash in the name",
|
||||
);
|
||||
|
||||
# #############################################################################
|
||||
# https://bugs.launchpad.net/percona-toolkit/+bug/1195034
|
||||
# pt-deadlock-logger error: Use of uninitialized value $ts in pattern match
|
||||
# #############################################################################
|
||||
|
||||
$innodb_status_sample = load_file("t/pt-deadlock-logger/samples/bug_1195034.txt");
|
||||
my $deadlocks = pt_deadlock_logger::parse_deadlocks($innodb_status_sample);
|
||||
|
||||
is_deeply(
|
||||
$deadlocks,
|
||||
{
|
||||
},
|
||||
"Bug 1195034: TOO DEEP OR LONG SEARCH IN THE LOCK TABLE WAITS-FOR GRAPH"
|
||||
) or diag(Dumper($deadlocks));
|
||||
|
||||
# #############################################################################
|
||||
# Done.
|
||||
# #############################################################################
|
||||
|
14
t/pt-deadlock-logger/samples/bug_1195034.txt
Normal file
14
t/pt-deadlock-logger/samples/bug_1195034.txt
Normal file
@@ -0,0 +1,14 @@
|
||||
|
||||
------------------------
|
||||
LATEST DETECTED DEADLOCK
|
||||
------------------------
|
||||
130624 17:39:24TOO DEEP OR LONG SEARCH IN THE LOCK TABLE WAITS-FOR GRAPH, WE WILL ROLL BACK FOLLOWING TRANSACTION
|
||||
|
||||
*** TRANSACTION:
|
||||
TRANSACTION 3BF88F886, ACTIVE 0 sec setting auto-inc lock
|
||||
mysql tables in use 1, locked 1
|
||||
1 lock struct(s), heap size 376, 0 row lock(s)
|
||||
MySQL thread id 23512694, OS thread handle 0x5055b940, query id 734303798 10.10.10.1 host update
|
||||
INSERT INTO gr_v3_response_log (query_key, time_received, time_to_respond, status, raw_response, api_host, api_path, api_client) VALUES ('...
|
||||
*** WAITING FOR THIS LOCK TO BE GRANTED:
|
||||
TABLE LOCK table `db`.`gr_v3_response_log` trx id 3BF88F886 lock mode AUTO-INC waiting
|
@@ -12,6 +12,8 @@ use English qw(-no_match_vars);
|
||||
use Test::More;
|
||||
use Time::HiRes qw(sleep);
|
||||
|
||||
$ENV{PTTEST_FAKE_TS} = 1;
|
||||
|
||||
use PerconaTest;
|
||||
use Sandbox;
|
||||
require "$trunk/bin/pt-online-schema-change";
|
||||
@@ -696,7 +698,7 @@ ok(
|
||||
"$sample/stats-dry-run.txt",
|
||||
),
|
||||
"--statistics --dry-run"
|
||||
);
|
||||
) or diag($test_diff);
|
||||
|
||||
ok(
|
||||
no_diff(
|
||||
@@ -709,7 +711,7 @@ ok(
|
||||
: "$sample/stats-execute.txt"),
|
||||
),
|
||||
"--statistics --execute"
|
||||
);
|
||||
) or diag($test_diff);
|
||||
|
||||
# #############################################################################
|
||||
# --default-engine
|
||||
|
@@ -77,9 +77,11 @@ $sb->load_file('master', "$sample/bug-1002448.sql");
|
||||
);
|
||||
|
||||
|
||||
unlike $output,
|
||||
qr/\QThe new table `test1002448`.`_table_name_new` does not have a PRIMARY KEY or a unique index which is required for the DELETE trigger/,
|
||||
"Bug 1002448: mistakenly uses indexes instead of keys";
|
||||
unlike(
|
||||
$output,
|
||||
qr/\QThe new table `test1002448`.`_table_name_new` does not have a PRIMARY KEY or a unique index which is required for the DELETE trigger/,
|
||||
"Bug 1002448: mistakenly uses indexes instead of keys"
|
||||
);
|
||||
|
||||
# ############################################################################
|
||||
# https://bugs.launchpad.net/percona-toolkit/+bug/1003315
|
||||
@@ -95,19 +97,26 @@ $sb->load_file('master', "$sample/bug-1003315.sql");
|
||||
"--alter-foreign-keys-method", "auto",
|
||||
"--dry-run",
|
||||
qw(--chunk-size 2 --dry-run --print))
|
||||
|
||||
},
|
||||
);
|
||||
|
||||
is $exit_status, 0, "Bug 1003315: Correct exit value for a dry run";
|
||||
is(
|
||||
$exit_status,
|
||||
0,
|
||||
"Bug 1003315: Correct exit value for a dry run"
|
||||
);
|
||||
|
||||
unlike $output,
|
||||
unlike(
|
||||
$output,
|
||||
qr/\QError updating foreign key constraints: Invalid --alter-foreign-keys-method:/,
|
||||
"Bug 1003315: No error when combining --alter-foreign-keys-method auto and --dry-run";
|
||||
"Bug 1003315: No error when combining --alter-foreign-keys-method auto and --dry-run"
|
||||
);
|
||||
|
||||
like $output,
|
||||
qr/\QNot updating foreign key constraints because this is a dry run./,
|
||||
"Bug 1003315: But now we do get an explanation from --dry-run";
|
||||
like(
|
||||
$output,
|
||||
qr/\QNot updating foreign key constraints because this is a dry run./,
|
||||
"Bug 1003315: But now we do get an explanation from --dry-run"
|
||||
);
|
||||
|
||||
# ############################################################################
|
||||
# This fakes the conditions to trigger the chunk index error
|
||||
@@ -174,9 +183,11 @@ for my $i ( 0..4 ) {
|
||||
$master_dbh->do(qq{create table `bug_1041372`.$tbl (a INT NOT NULL AUTO_INCREMENT PRIMARY KEY )});
|
||||
$master_dbh->do(qq{insert into `bug_1041372`.$tbl values (1), (2), (3), (4), (5)});
|
||||
|
||||
($output) = full_output(sub { pt_online_schema_change::main(@args,
|
||||
'--alter', "ADD COLUMN ptosc INT",
|
||||
'--execute', "$master_dsn,D=bug_1041372,t=$tbl")});
|
||||
($output) = full_output(sub {
|
||||
pt_online_schema_change::main(@args,
|
||||
'--alter', "ADD COLUMN ptosc INT",
|
||||
'--execute', "$master_dsn,D=bug_1041372,t=$tbl")
|
||||
});
|
||||
|
||||
like(
|
||||
$output,
|
||||
@@ -261,7 +272,6 @@ $sb->load_file('master', "$sample/del-trg-bug-1062324.sql");
|
||||
undef,
|
||||
"Delete trigger works after altering PK (bug 1103672)"
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
# #############################################################################
|
||||
@@ -293,6 +303,72 @@ else {
|
||||
);
|
||||
}
|
||||
|
||||
# ############################################################################
|
||||
# https://bugs.launchpad.net/percona-toolkit/+bug/1171653
|
||||
#
|
||||
# ############################################################################
|
||||
$sb->load_file('master', "$sample/utf8_charset_tbl.sql");
|
||||
|
||||
($output, $exit_status) = full_output(
|
||||
sub { pt_online_schema_change::main(@args,
|
||||
"$master_dsn,D=test1171653,t=t",
|
||||
"--alter", "drop column foo",
|
||||
qw(--execute --print))
|
||||
},
|
||||
);
|
||||
|
||||
my $row = $master_dbh->selectrow_arrayref("SHOW CREATE TABLE test1171653.t");
|
||||
|
||||
like(
|
||||
$row->[1],
|
||||
qr/DEFAULT CHARSET=utf8/,
|
||||
"Bug 1171653: table charset is not preserved"
|
||||
);
|
||||
|
||||
# #############################################################################
|
||||
# https://bugs.launchpad.net/percona-toolkit/+bug/1188264
|
||||
# pt-online-schema-change error copying rows: Undefined subroutine
|
||||
# &pt_online_schema_change::get
|
||||
# #############################################################################
|
||||
|
||||
# In exec_nibble() we had:
|
||||
# if ( get('statistics') ) {
|
||||
# $err .= "but further occurrences will be reported "
|
||||
# . "by --statistics when the tool finishes.\n";
|
||||
# }
|
||||
# which is called when copying rows causes a MySQL warning
|
||||
# for the first time. So to test this code path, we need to
|
||||
# cause a MySQL warning while copying rows.
|
||||
|
||||
$sb->load_file('master', "$sample/basic_no_fks_innodb.sql");
|
||||
$master_dbh->do("INSERT INTO pt_osc.t VALUES (null, 'This string will be too long after we modify the table so it will cause a warning about the value being truncated in the new table. The other column values are a single character.', NOW())");
|
||||
|
||||
($output, $exit_status) = full_output(
|
||||
sub { pt_online_schema_change::main(@args,
|
||||
"$master_dsn,D=pt_osc,t=t",
|
||||
"--alter", "modify c varchar(8)",
|
||||
qw(--execute --print))
|
||||
},
|
||||
);
|
||||
|
||||
is(
|
||||
$exit_status,
|
||||
0,
|
||||
"Bug 1188264: 0 exit"
|
||||
);
|
||||
|
||||
unlike(
|
||||
$output,
|
||||
qr/Undefined subroutine/i,
|
||||
"Bug 1188264: no undefined subroutine"
|
||||
);
|
||||
|
||||
like(
|
||||
$output,
|
||||
qr/error 1265/, # Data truncated for column 'c' at row 21
|
||||
"Bug 1188264: warning about expected MySQL error 1265"
|
||||
);
|
||||
|
||||
# #############################################################################
|
||||
# Done.
|
||||
# #############################################################################
|
||||
|
69
t/pt-online-schema-change/charset.t
Normal file
69
t/pt-online-schema-change/charset.t
Normal file
@@ -0,0 +1,69 @@
|
||||
#!/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 Data::Dumper;
|
||||
use PerconaTest;
|
||||
use Sandbox;
|
||||
|
||||
require "$trunk/bin/pt-online-schema-change";
|
||||
|
||||
my $dp = new DSNParser(opts=>$dsn_opts);
|
||||
my $sb = new Sandbox(basedir => '/tmp', DSNParser => $dp);
|
||||
my $master_dbh = $sb->get_dbh_for('master');
|
||||
my $slave_dbh = $sb->get_dbh_for('slave1');
|
||||
|
||||
if ( !$master_dbh ) {
|
||||
plan skip_all => 'Cannot connect to sandbox master';
|
||||
}
|
||||
elsif ( !$slave_dbh ) {
|
||||
plan skip_all => 'Cannot connect to sandbox slave1';
|
||||
}
|
||||
|
||||
# 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.
|
||||
my $master_dsn = 'h=127.1,P=12345,u=msandbox,p=msandbox';
|
||||
my @args = (qw(--set-vars innodb_lock_wait_timeout=3));
|
||||
my $sample = "t/pt-online-schema-change/samples/";
|
||||
my $plugin = "$trunk/$sample/plugins";
|
||||
my $output;
|
||||
my $exit_status;
|
||||
|
||||
# ############################################################################
|
||||
# https://bugs.launchpad.net/percona-toolkit/+bug/1171653
|
||||
#
|
||||
# ############################################################################
|
||||
$sb->load_file('master', "$sample/basic_no_fks.sql");
|
||||
|
||||
($output, $exit_status) = full_output(
|
||||
sub { pt_online_schema_change::main(@args,
|
||||
"$master_dsn,D=pt_osc,t=t",
|
||||
"--alter", "CHARACTER SET utf8, MODIFY c CHAR(128) CHARACTER SET utf8",
|
||||
'--plugin', "$plugin/show_create_new_table.pm",
|
||||
qw(--quiet --execute)) },
|
||||
);
|
||||
|
||||
my @create = split("\n\n", $output);
|
||||
|
||||
like(
|
||||
$create[1],
|
||||
qr/DEFAULT CHARSET=utf8/,
|
||||
"Can alter charset of new table"
|
||||
);
|
||||
|
||||
# #############################################################################
|
||||
# Done.
|
||||
# #############################################################################
|
||||
$sb->wipe_clean($master_dbh);
|
||||
ok($sb->ok(), "Sandbox servers") or BAIL_OUT(__FILE__ . " broke the sandbox");
|
||||
done_testing;
|
@@ -0,0 +1,30 @@
|
||||
package pt_online_schema_change_plugin;
|
||||
|
||||
use strict;
|
||||
use warnings FATAL => 'all';
|
||||
use English qw(-no_match_vars);
|
||||
use constant PTDEBUG => $ENV{PTDEBUG} || 0;
|
||||
|
||||
sub new {
|
||||
my ($class, %args) = @_;
|
||||
my $self = { %args };
|
||||
return bless $self, $class;
|
||||
}
|
||||
|
||||
sub after_create_new_table {
|
||||
my ($self, %args) = @_;
|
||||
my $new_tbl = $args{new_tbl};
|
||||
my $dbh = $self->{cxn}->dbh;
|
||||
my $row = $dbh->selectrow_arrayref("SHOW CREATE TABLE $new_tbl->{name}");
|
||||
warn "after_create_new_table: $row->[1]\n\n";
|
||||
}
|
||||
|
||||
sub after_alter_new_table {
|
||||
my ($self, %args) = @_;
|
||||
my $new_tbl = $args{new_tbl};
|
||||
my $dbh = $self->{cxn}->dbh;
|
||||
my $row = $dbh->selectrow_arrayref("SHOW CREATE TABLE $new_tbl->{name}");
|
||||
warn "after_alter_new_table: $row->[1]\n\n";
|
||||
}
|
||||
|
||||
1;
|
@@ -6,8 +6,8 @@ Operation, tries, wait:
|
||||
update_foreign_keys, 10, 1
|
||||
Starting a dry run. `bug_1045317`.`bits` will not be altered. Specify --execute instead of --dry-run to alter the table.
|
||||
Not dropping triggers because this is a dry run.
|
||||
Dropping new table...
|
||||
Dropped new table OK.
|
||||
TS Dropping new table...
|
||||
TS Dropped new table OK.
|
||||
# Event Count
|
||||
# ====== =====
|
||||
# INSERT 0
|
||||
|
@@ -5,8 +5,8 @@ Operation, tries, wait:
|
||||
swap_tables, 10, 1
|
||||
update_foreign_keys, 10, 1
|
||||
Altering `bug_1045317`.`bits`...
|
||||
Dropping triggers...
|
||||
Dropped triggers OK.
|
||||
TS Dropping triggers...
|
||||
TS Dropped triggers OK.
|
||||
# Event Count
|
||||
# ================== =====
|
||||
# INSERT 1
|
||||
@@ -16,11 +16,11 @@ Creating new table...
|
||||
Created new table bug_1045317._bits_new OK.
|
||||
Altering new table...
|
||||
Altered `bug_1045317`.`_bits_new` OK.
|
||||
Creating triggers...
|
||||
Created triggers OK.
|
||||
Copying approximately 3 rows...
|
||||
Copied rows OK.
|
||||
Swapping tables...
|
||||
Swapped original and new tables OK.
|
||||
Dropping old table...
|
||||
Dropped old table `bug_1045317`.`_bits_old` OK.
|
||||
TS Creating triggers...
|
||||
TS Created triggers OK.
|
||||
TS Copying approximately 3 rows...
|
||||
TS Copied rows OK.
|
||||
TS Swapping tables...
|
||||
TS Swapped original and new tables OK.
|
||||
TS Dropping old table...
|
||||
TS Dropped old table `bug_1045317`.`_bits_old` OK.
|
||||
|
11
t/pt-online-schema-change/samples/utf8_charset_tbl.sql
Normal file
11
t/pt-online-schema-change/samples/utf8_charset_tbl.sql
Normal file
@@ -0,0 +1,11 @@
|
||||
drop database if exists test1171653;
|
||||
create database test1171653;
|
||||
use test1171653;
|
||||
|
||||
CREATE TABLE `t` (
|
||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`foo` varchar(30) NOT NULL,
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||
|
||||
INSERT INTO `t` VALUES (1,'bar'), (2,'bar2'), (3,'bar3');
|
@@ -20,12 +20,12 @@ local $JSONReportFormatter::pretty_json = 1;
|
||||
|
||||
my @args = qw(--output json);
|
||||
my $sample = "$trunk/t/lib/samples";
|
||||
my $results = "t/pt-query-digest/samples";
|
||||
my $results = "t/pt-query-digest/samples/json";
|
||||
|
||||
ok(
|
||||
no_diff(
|
||||
sub { pt_query_digest::main(@args, "$sample/slowlogs/empty") },
|
||||
"$results/empty_report.txt",
|
||||
"t/pt-query-digest/samples/empty_report.txt",
|
||||
),
|
||||
'json output for empty log'
|
||||
) or diag($test_diff);
|
||||
@@ -33,18 +33,30 @@ ok(
|
||||
ok(
|
||||
no_diff(
|
||||
sub { pt_query_digest::main(@args, "$sample/slowlogs/slow002.txt") },
|
||||
"$results/output_json_slow002.txt"
|
||||
"$results/slow002.txt",
|
||||
sed => [ qq/'s!$trunk!TRUNK!'/ ],
|
||||
),
|
||||
'json output for slow002'
|
||||
) or diag($test_diff);
|
||||
|
||||
ok(
|
||||
no_diff(
|
||||
sub { pt_query_digest::main(qw(--output json-anon),
|
||||
"$sample/slowlogs/slow002.txt") },
|
||||
"$results/slow002-anon.txt",
|
||||
sed => [ qq/'s!$trunk!TRUNK!'/ ],
|
||||
),
|
||||
'json-anon output for slow002'
|
||||
) or diag($test_diff);
|
||||
|
||||
# --type tcpdump
|
||||
|
||||
ok(
|
||||
no_diff(
|
||||
sub { pt_query_digest::main(qw(--type tcpdump --limit 10 --watch-server 127.0.0.1:12345),
|
||||
@args, "$sample/tcpdump/tcpdump021.txt") },
|
||||
"$results/output_json_tcpdump021.txt",
|
||||
"$results/tcpdump021.txt",
|
||||
sed => [ qq/'s!$trunk!TRUNK!'/ ],
|
||||
),
|
||||
'json output for for tcpdump021',
|
||||
) or diag($test_diff);
|
||||
|
@@ -1,2 +0,0 @@
|
||||
|
||||
# No events processed.
|
||||
|
257
t/pt-query-digest/samples/json/slow002-anon.txt
Normal file
257
t/pt-query-digest/samples/json/slow002-anon.txt
Normal file
@@ -0,0 +1,257 @@
|
||||
|
||||
{
|
||||
"classes" : [
|
||||
{
|
||||
"attribute" : "fingerprint",
|
||||
"checksum" : "66825DDC008FFA89",
|
||||
"distillate" : "UPDATE db?.tuningdetail_?_? db?.gonzo",
|
||||
"fingerprint" : "update d?tuningdetail_?_? n inner join d?gonzo a using(gonzo) set n.column? = a.column?, n.word? = a.word?",
|
||||
"metrics" : {
|
||||
"Filesort" : {
|
||||
"yes" : "0"
|
||||
},
|
||||
"Filesort_on_disk" : {
|
||||
"yes" : "0"
|
||||
},
|
||||
"Full_join" : {
|
||||
"yes" : "0"
|
||||
},
|
||||
"Full_scan" : {
|
||||
"yes" : "1"
|
||||
},
|
||||
"Lock_time" : {
|
||||
"avg" : "0.000091",
|
||||
"max" : "0.000091",
|
||||
"median" : "0.000091",
|
||||
"min" : "0.000091",
|
||||
"pct" : "0.125000",
|
||||
"pct_95" : "0.000091",
|
||||
"stddev" : "0.000000",
|
||||
"sum" : "0.000091"
|
||||
},
|
||||
"Merge_passes" : {
|
||||
"avg" : "0",
|
||||
"max" : "0",
|
||||
"median" : "0",
|
||||
"min" : "0",
|
||||
"pct" : "0",
|
||||
"pct_95" : "0",
|
||||
"stddev" : "0",
|
||||
"sum" : "0"
|
||||
},
|
||||
"QC_Hit" : {
|
||||
"yes" : "0"
|
||||
},
|
||||
"Query_length" : {
|
||||
"avg" : "129",
|
||||
"max" : "129",
|
||||
"median" : "129",
|
||||
"min" : "129",
|
||||
"pct" : "0",
|
||||
"pct_95" : "129",
|
||||
"stddev" : "0",
|
||||
"sum" : "129"
|
||||
},
|
||||
"Query_time" : {
|
||||
"avg" : "0.726052",
|
||||
"max" : "0.726052",
|
||||
"median" : "0.726052",
|
||||
"min" : "0.726052",
|
||||
"pct" : "0.125000",
|
||||
"pct_95" : "0.726052",
|
||||
"stddev" : "0.000000",
|
||||
"sum" : "0.726052"
|
||||
},
|
||||
"Rows_examined" : {
|
||||
"avg" : "62951",
|
||||
"max" : "62951",
|
||||
"median" : "62951",
|
||||
"min" : "62951",
|
||||
"pct" : "0",
|
||||
"pct_95" : "62951",
|
||||
"stddev" : "0",
|
||||
"sum" : "62951"
|
||||
},
|
||||
"Rows_sent" : {
|
||||
"avg" : "0",
|
||||
"max" : "0",
|
||||
"median" : "0",
|
||||
"min" : "0",
|
||||
"pct" : "0",
|
||||
"pct_95" : "0",
|
||||
"stddev" : "0",
|
||||
"sum" : "0"
|
||||
},
|
||||
"Tmp_table" : {
|
||||
"yes" : "0"
|
||||
},
|
||||
"Tmp_table_on_disk" : {
|
||||
"yes" : "0"
|
||||
},
|
||||
"db" : {
|
||||
"value" : "db1"
|
||||
},
|
||||
"host" : {
|
||||
"value" : ""
|
||||
},
|
||||
"user" : {
|
||||
"value" : "[SQL_SLAVE]"
|
||||
}
|
||||
},
|
||||
"query_count" : 1,
|
||||
"tables" : [
|
||||
{
|
||||
"create" : "SHOW CREATE TABLE `db2`.`tuningdetail_21_265507`\\G",
|
||||
"status" : "SHOW TABLE STATUS FROM `db2` LIKE 'tuningdetail_21_265507'\\G"
|
||||
},
|
||||
{
|
||||
"create" : "SHOW CREATE TABLE `db1`.`gonzo`\\G",
|
||||
"status" : "SHOW TABLE STATUS FROM `db1` LIKE 'gonzo'\\G"
|
||||
}
|
||||
],
|
||||
"ts_max" : "2007-12-18 11:48:27",
|
||||
"ts_min" : "2007-12-18 11:48:27"
|
||||
}
|
||||
],
|
||||
"global" : {
|
||||
"files" : [
|
||||
{
|
||||
"name" : "TRUNK/t/lib/samples/slowlogs/slow002.txt",
|
||||
"size" : 3841
|
||||
}
|
||||
],
|
||||
"metrics" : {
|
||||
"Filesort" : {
|
||||
"cnt" : "0"
|
||||
},
|
||||
"Filesort_on_disk" : {
|
||||
"cnt" : "0"
|
||||
},
|
||||
"Full_join" : {
|
||||
"cnt" : "0"
|
||||
},
|
||||
"Full_scan" : {
|
||||
"cnt" : "1"
|
||||
},
|
||||
"InnoDB_IO_r_bytes" : {
|
||||
"avg" : "0",
|
||||
"max" : "0",
|
||||
"median" : "0",
|
||||
"min" : "0",
|
||||
"pct_95" : "0",
|
||||
"stddev" : "0",
|
||||
"sum" : "0"
|
||||
},
|
||||
"InnoDB_IO_r_ops" : {
|
||||
"avg" : "0",
|
||||
"max" : "0",
|
||||
"median" : "0",
|
||||
"min" : "0",
|
||||
"pct_95" : "0",
|
||||
"stddev" : "0",
|
||||
"sum" : "0"
|
||||
},
|
||||
"InnoDB_IO_r_wait" : {
|
||||
"avg" : "0.000000",
|
||||
"max" : "0.000000",
|
||||
"median" : "0.000000",
|
||||
"min" : "0.000000",
|
||||
"pct_95" : "0.000000",
|
||||
"stddev" : "0.000000",
|
||||
"sum" : "0.000000"
|
||||
},
|
||||
"InnoDB_pages_distinct" : {
|
||||
"avg" : "17",
|
||||
"max" : "24",
|
||||
"median" : "17",
|
||||
"min" : "11",
|
||||
"pct_95" : "23",
|
||||
"stddev" : "3",
|
||||
"sum" : "107"
|
||||
},
|
||||
"InnoDB_queue_wait" : {
|
||||
"avg" : "0.000000",
|
||||
"max" : "0.000000",
|
||||
"median" : "0.000000",
|
||||
"min" : "0.000000",
|
||||
"pct_95" : "0.000000",
|
||||
"stddev" : "0.000000",
|
||||
"sum" : "0.000000"
|
||||
},
|
||||
"InnoDB_rec_lock_wait" : {
|
||||
"avg" : "0.000000",
|
||||
"max" : "0.000000",
|
||||
"median" : "0.000000",
|
||||
"min" : "0.000000",
|
||||
"pct_95" : "0.000000",
|
||||
"stddev" : "0.000000",
|
||||
"sum" : "0.000000"
|
||||
},
|
||||
"Lock_time" : {
|
||||
"avg" : "0.000038",
|
||||
"max" : "0.000091",
|
||||
"median" : "0.000026",
|
||||
"min" : "0.000000",
|
||||
"pct_95" : "0.000089",
|
||||
"stddev" : "0.000028",
|
||||
"sum" : "0.000304"
|
||||
},
|
||||
"Merge_passes" : {
|
||||
"avg" : "0",
|
||||
"max" : "0",
|
||||
"median" : "0",
|
||||
"min" : "0",
|
||||
"pct_95" : "0",
|
||||
"stddev" : "0",
|
||||
"sum" : "0"
|
||||
},
|
||||
"QC_Hit" : {
|
||||
"cnt" : "0"
|
||||
},
|
||||
"Query_length" : {
|
||||
"avg" : "62",
|
||||
"max" : "129",
|
||||
"median" : "62",
|
||||
"min" : "5",
|
||||
"pct_95" : "124",
|
||||
"stddev" : "34",
|
||||
"sum" : "502"
|
||||
},
|
||||
"Query_time" : {
|
||||
"avg" : "0.095260",
|
||||
"max" : "0.726052",
|
||||
"median" : "0.000516",
|
||||
"min" : "0.000012",
|
||||
"pct_95" : "0.705093",
|
||||
"stddev" : "0.231765",
|
||||
"sum" : "0.762080"
|
||||
},
|
||||
"Rows_examined" : {
|
||||
"avg" : "7868",
|
||||
"max" : "62951",
|
||||
"median" : "0",
|
||||
"min" : "0",
|
||||
"pct_95" : "61003",
|
||||
"stddev" : "20174",
|
||||
"sum" : "62951"
|
||||
},
|
||||
"Rows_sent" : {
|
||||
"avg" : "0",
|
||||
"max" : "0",
|
||||
"median" : "0",
|
||||
"min" : "0",
|
||||
"pct_95" : "0",
|
||||
"stddev" : "0",
|
||||
"sum" : "0"
|
||||
},
|
||||
"Tmp_table" : {
|
||||
"cnt" : "0"
|
||||
},
|
||||
"Tmp_table_on_disk" : {
|
||||
"cnt" : "0"
|
||||
}
|
||||
},
|
||||
"query_count" : 8,
|
||||
"unique_query_count" : 7
|
||||
}
|
||||
}
|
@@ -121,7 +121,7 @@
|
||||
"global" : {
|
||||
"files" : [
|
||||
{
|
||||
"name" : "/Users/daniel/p/release-2.2.3/t/lib/samples/slowlogs/slow002.txt",
|
||||
"name" : "TRUNK/t/lib/samples/slowlogs/slow002.txt",
|
||||
"size" : 3841
|
||||
}
|
||||
],
|
@@ -187,7 +187,7 @@
|
||||
"global" : {
|
||||
"files" : [
|
||||
{
|
||||
"name" : "/Users/daniel/p/release-2.2.3/t/lib/samples/tcpdump/tcpdump021.txt",
|
||||
"name" : "TRUNK/t/lib/samples/tcpdump/tcpdump021.txt",
|
||||
"size" : 2827
|
||||
}
|
||||
],
|
29
t/pt-query-digest/samples/slow057.txt
Normal file
29
t/pt-query-digest/samples/slow057.txt
Normal file
@@ -0,0 +1,29 @@
|
||||
|
||||
# ########################################################################
|
||||
# Report grouped by db
|
||||
# ########################################################################
|
||||
|
||||
# Item 1: 0 QPS, 0x concurrency, ID 0x585AC494268B351B at byte 434 _______
|
||||
# This item is included in the report because it matches --limit.
|
||||
# Scores: V/M = 0.01
|
||||
# Attribute pct total min max avg 95% stddev median
|
||||
# ============ === ======= ======= ======= ======= ======= ======= =======
|
||||
# Count 100 4
|
||||
# Exec time 100 21ms 2us 19ms 5ms 18ms 8ms 881us
|
||||
# Lock time 100 9ms 0 9ms 2ms 9ms 4ms 0
|
||||
# Rows sent 0 0 0 0 0 0 0 0
|
||||
# Rows examine 0 0 0 0 0 0 0 0
|
||||
# Query size 100 82 14 27 20.50 26.08 6.12 26.08
|
||||
# String:
|
||||
# Hosts
|
||||
# Users meow
|
||||
# Query_time distribution
|
||||
# 1us ################################
|
||||
# 10us
|
||||
# 100us ################################################################
|
||||
# 1ms
|
||||
# 10ms ################################
|
||||
# 100ms
|
||||
# 1s
|
||||
# 10s+
|
||||
db
|
@@ -393,6 +393,19 @@ ok(
|
||||
'Analysis for slow056 (no query bug 1082599)'
|
||||
);
|
||||
|
||||
# #############################################################################
|
||||
# Bug 1176010: pt-query-digest should know how to group quoted and unquoted database names
|
||||
# https://bugs.launchpad.net/percona-toolkit/+bug/1176010
|
||||
#############################################################################
|
||||
ok(
|
||||
no_diff(
|
||||
sub { pt_query_digest::main(@args, $sample.'slow057.txt',
|
||||
qw(--group-by db)) },
|
||||
"t/pt-query-digest/samples/slow057.txt",
|
||||
),
|
||||
'Analysis for slow057 (no grouping bug 1176010)'
|
||||
) or diag($test_diff);
|
||||
|
||||
# #############################################################################
|
||||
# Done.
|
||||
# #############################################################################
|
||||
|
@@ -80,7 +80,7 @@ my $create_repl_table =
|
||||
this_cnt int NOT NULL,
|
||||
master_crc char(40) NULL,
|
||||
master_cnt int NULL,
|
||||
ts timestamp NOT NULL,
|
||||
ts timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
PRIMARY KEY (db, tbl, chunk)
|
||||
) ENGINE=InnoDB;";
|
||||
|
||||
|
@@ -12,6 +12,6 @@ CREATE TABLE truncated_checksums (
|
||||
this_cnt int NOT NULL,
|
||||
master_crc char(40) NULL,
|
||||
master_cnt int NULL,
|
||||
ts timestamp NOT NULL,
|
||||
ts timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
PRIMARY KEY (db, tbl, chunk)
|
||||
) ENGINE=InnoDB;
|
||||
|
@@ -0,0 +1 @@
|
||||
explicit_defaults_for_timestamp=ON
|
57
t/pt-table-checksum/settings.t
Normal file
57
t/pt-table-checksum/settings.t
Normal file
@@ -0,0 +1,57 @@
|
||||
#!/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;
|
||||
require "$trunk/bin/pt-table-checksum";
|
||||
|
||||
if ( $sandbox_version lt '5.6' ) {
|
||||
plan skip_all => 'Tests for MySQL 5.6';
|
||||
}
|
||||
|
||||
diag(`$trunk/sandbox/stop-sandbox 12348 >/dev/null`);
|
||||
diag(`EXTRA_DEFAULTS_FILE="$trunk/t/pt-table-checksum/samples/explicit_defaults_for_timestamp.cnf" $trunk/sandbox/start-sandbox master 12348 >/dev/null`);
|
||||
|
||||
my $dp = new DSNParser(opts=>$dsn_opts);
|
||||
my $sb = new Sandbox(basedir => '/tmp', DSNParser => $dp);
|
||||
my $master_dbh = $sb->get_dbh_for('master1');
|
||||
|
||||
if ( !$master_dbh ) {
|
||||
plan skip_all => 'Cannot connect to sandbox master 12348';
|
||||
}
|
||||
|
||||
my $master_dsn = 'h=127.1,P=12348,u=msandbox,p=msandbox';
|
||||
my @args = ($master_dsn, '--max-load', '');
|
||||
my $output;
|
||||
my $retval;
|
||||
|
||||
$output = output(
|
||||
sub { $retval = pt_table_checksum::main(@args, qw(-t mysql.user)) },
|
||||
stderr => 1,
|
||||
);
|
||||
|
||||
unlike(
|
||||
$output,
|
||||
qr/error 1364/i,
|
||||
"explicit_defaults_for_timestamp (bug 1163735): no error"
|
||||
);
|
||||
|
||||
# Exit will be non-zero because of "Diffs cannot be detected because
|
||||
# no slaves were found."
|
||||
|
||||
# #############################################################################
|
||||
# Done.
|
||||
# #############################################################################
|
||||
diag(`$trunk/sandbox/stop-sandbox 12348 >/dev/null`);
|
||||
ok($sb->ok(), "Sandbox servers") or BAIL_OUT(__FILE__ . " broke the sandbox");
|
||||
done_testing;
|
@@ -111,6 +111,20 @@ test_diff (
|
||||
],
|
||||
);
|
||||
|
||||
# #############################################################################
|
||||
# https://bugs.launchpad.net/percona-toolkit/+bug/1168434
|
||||
# pt-upgrade reports differences on NULL
|
||||
# #############################################################################
|
||||
|
||||
$sb->load_file('master', "t/pt-upgrade/samples/007/tables.sql");
|
||||
|
||||
test_diff(
|
||||
name => 'Bug 1168434: no diff with NULL',
|
||||
query1 => 'select * from test.t order by id',
|
||||
query2 => 'select * from test.t order by id',
|
||||
expect => [],
|
||||
);
|
||||
|
||||
# #############################################################################
|
||||
# Done.
|
||||
# #############################################################################
|
||||
|
4
t/pt-upgrade/samples/007/null.log
Normal file
4
t/pt-upgrade/samples/007/null.log
Normal file
@@ -0,0 +1,4 @@
|
||||
# User@Host: root[root] @ localhost []
|
||||
# Query_time: 1 Lock_time: 0 Rows_sent: 7 Rows_examined: 7
|
||||
use test;
|
||||
select * from test.t order by id;
|
35
t/pt-upgrade/samples/007/null.txt
Normal file
35
t/pt-upgrade/samples/007/null.txt
Normal file
@@ -0,0 +1,35 @@
|
||||
|
||||
#-----------------------------------------------------------------------
|
||||
# Logs
|
||||
#-----------------------------------------------------------------------
|
||||
|
||||
File: ...
|
||||
Size: 145
|
||||
|
||||
#-----------------------------------------------------------------------
|
||||
# Hosts
|
||||
#-----------------------------------------------------------------------
|
||||
|
||||
host1:
|
||||
|
||||
DSN: h=127.1,P=12345
|
||||
hostname: ...
|
||||
MySQL: ...
|
||||
|
||||
host2:
|
||||
|
||||
DSN: h=127.1,P=12348
|
||||
hostname: ...
|
||||
MySQL: ...
|
||||
|
||||
#-----------------------------------------------------------------------
|
||||
# Stats
|
||||
#-----------------------------------------------------------------------
|
||||
|
||||
failed_queries 0
|
||||
not_select 0
|
||||
queries_filtered 0
|
||||
queries_no_diffs 1
|
||||
queries_read 1
|
||||
queries_with_diffs 0
|
||||
queries_with_errors 0
|
32
t/pt-upgrade/samples/007/null_results.txt
Normal file
32
t/pt-upgrade/samples/007/null_results.txt
Normal file
@@ -0,0 +1,32 @@
|
||||
|
||||
#-----------------------------------------------------------------------
|
||||
# Logs
|
||||
#-----------------------------------------------------------------------
|
||||
|
||||
Results directory: ...
|
||||
|
||||
#-----------------------------------------------------------------------
|
||||
# Hosts
|
||||
#-----------------------------------------------------------------------
|
||||
|
||||
host1:
|
||||
|
||||
Reading results from ...
|
||||
|
||||
host2:
|
||||
|
||||
DSN: h=127.1,P=12348
|
||||
hostname: ...
|
||||
MySQL: ...
|
||||
|
||||
#-----------------------------------------------------------------------
|
||||
# Stats
|
||||
#-----------------------------------------------------------------------
|
||||
|
||||
failed_queries 0
|
||||
not_select 0
|
||||
queries_filtered 0
|
||||
queries_no_diffs 1
|
||||
queries_read 1
|
||||
queries_with_diffs 0
|
||||
queries_with_errors 0
|
3
t/pt-upgrade/samples/007/null_results/query
Normal file
3
t/pt-upgrade/samples/007/null_results/query
Normal file
@@ -0,0 +1,3 @@
|
||||
use `test`;
|
||||
select * from test.t order by id
|
||||
##
|
6
t/pt-upgrade/samples/007/null_results/results
Normal file
6
t/pt-upgrade/samples/007/null_results/results
Normal file
@@ -0,0 +1,6 @@
|
||||
$results = {
|
||||
query_time => '0',
|
||||
warnings => {}
|
||||
};
|
||||
|
||||
##
|
12
t/pt-upgrade/samples/007/null_results/rows
Normal file
12
t/pt-upgrade/samples/007/null_results/rows
Normal file
@@ -0,0 +1,12 @@
|
||||
$rows = [
|
||||
[
|
||||
'1',
|
||||
'a'
|
||||
],
|
||||
[
|
||||
'2',
|
||||
undef
|
||||
]
|
||||
];
|
||||
|
||||
##
|
11
t/pt-upgrade/samples/007/tables.sql
Normal file
11
t/pt-upgrade/samples/007/tables.sql
Normal file
@@ -0,0 +1,11 @@
|
||||
DROP DATABASE IF EXISTS test;
|
||||
CREATE DATABASE test;
|
||||
USE test;
|
||||
CREATE TABLE t (
|
||||
id int(10) NOT NULL AUTO_INCREMENT,
|
||||
username varchar(8) default NULL,
|
||||
PRIMARY KEY (`id`)
|
||||
);
|
||||
INSERT INTO t VALUES
|
||||
(null, 'a'),
|
||||
(null, null);
|
50
t/pt-variable-advisor/advice.t
Normal file
50
t/pt-variable-advisor/advice.t
Normal file
@@ -0,0 +1,50 @@
|
||||
#!/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;
|
||||
require "$trunk/bin/pt-variable-advisor";
|
||||
|
||||
my $dp = new DSNParser(opts=>$dsn_opts);
|
||||
my $sb = new Sandbox(basedir => '/tmp', DSNParser => $dp);
|
||||
my $dbh = $sb->get_dbh_for('master');
|
||||
my $dsn = $sb->dsn_for('master');
|
||||
|
||||
if ( !$dbh ) {
|
||||
plan skip_all => "Cannot connect to sandbox master";
|
||||
}
|
||||
|
||||
# #############################################################################
|
||||
# https://bugs.launchpad.net/percona-toolkit/+bug/1168106
|
||||
# pt-variable-advisor has the wrong default value for
|
||||
# innodb_max_dirty_pages_pct in 5.6.10
|
||||
# #############################################################################
|
||||
|
||||
my @args = "$dsn";
|
||||
my $output = "";
|
||||
|
||||
$output = output(
|
||||
sub { pt_variable_advisor::main(@args) },
|
||||
);
|
||||
|
||||
unlike(
|
||||
$output,
|
||||
qr/innodb_max_dirty_pages_pct/,
|
||||
"No innodb_max_dirty_pages_pct warning (bug 1168106)"
|
||||
);
|
||||
|
||||
# #############################################################################
|
||||
# Done.
|
||||
# #############################################################################
|
||||
ok($sb->ok(), "Sandbox servers") or BAIL_OUT(__FILE__ . " broke the sandbox");
|
||||
done_testing;
|
Reference in New Issue
Block a user