Merge branch '3.x' into galera-log-explainer

This commit is contained in:
Sveta Smirnova
2023-11-30 20:12:22 +03:00
committed by Sveta Smirnova
47 changed files with 1828 additions and 118 deletions

15
.editorconfig Normal file
View File

@@ -0,0 +1,15 @@
root = true
[*]
indent_style = space
indent_size = 4
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true
[{*.pm,bin/*}]
indent_size = 3
[*.go]
indent_style = tab

View File

@@ -25,9 +25,9 @@ jobs:
run: cd src/go; make linux-amd64; cd ../../
- name: Build the Docker image
run: echo "FROM oraclelinux:9-slim" > Dockerfile; echo "COPY bin/* /usr/bin/" >> Dockerfile; docker build . --file Dockerfile --tag percona-toolkit:${{ github.sha }}
run: echo "FROM oraclelinux:9-slim" > Dockerfile; echo "RUN microdnf -y update" >> Dockerfile; echo "COPY bin/* /usr/bin/" >> Dockerfile; docker build . --file Dockerfile --tag percona-toolkit:${{ github.sha }}
- name: Run Trivy vulnerability scanner
uses: aquasecurity/trivy-action@0.12.0
uses: aquasecurity/trivy-action@0.14.0
with:
image-ref: 'percona-toolkit:${{ github.sha }}'
format: 'table'

View File

@@ -1,20 +1,38 @@
use ExtUtils::MakeMaker;
use ExtUtils::MY;
sub MY::postamble {
return <<'MAKE_GOTOOLS';
gotools:
cd src/go && $(MAKE) build
MAKE_GOTOOLS
}
WriteMakefile(
NAME => 'Percona::Toolkit',
VERSION => '3.5.5',
EXE_FILES => [ <bin/*> ],
EXE_FILES => [
map {
(my $name = $_) =~ s/^bin.//;
my $file_name = $_;
if ( ( $file_name !~ m/mongo/ ) || ( $file_name !~ m/pg/ ) || ( $file_name !~ m/pt-stalk/ ) || ( $file_name !~ m/pt-k8s/ ) ) {
$_;
}
} <bin/*>
],
MAN1PODS => {
'docs/percona-toolkit.pod' => 'blib/man1/percona-toolkit.1p',
map {
(my $name = $_) =~ s/^bin.//;
my $file_name = $_;
if ( ( $file_name !~ m/mongo/ ) || ( $file_name !~ m/pg/ ) || ( $file_name !~ m/pt-stalk/ ) ) {
if ( ( $file_name !~ m/mongo/ ) || ( $file_name !~ m/pg/ ) || ( $file_name !~ m/pt-stalk/ ) || ( $file_name !~ m/pt-k8s/ ) ) {
$_ => "blib/man1/$name.1p";
}
} <bin/*>
},
MAN3PODS => {}, # man(3) pages are for C libs
depend => {manifypods => gotools},
PREREQ_PM => {
DBI => 1.46,
DBD::mysql => 3.0000_0,

View File

@@ -6401,7 +6401,7 @@ sub main {
$tp->get_create_table( $dbh, $table->{D}, $table->{t} ));
if ( $o->get('check-charset') ) {
my $sql = 'SELECT CONCAT(/*!40100 @@session.character_set_connection, */ "")';
my $sql = 'SELECT CONCAT(/*!40100 @@session.character_set_connection, */ \'\')';
PTDEBUG && _d($sql);
my ($dbh_charset) = $table->{dbh}->selectrow_array($sql);
@@ -6786,8 +6786,8 @@ sub main {
}
my $charset = $got_charset || '';
if ($charset eq 'utf8') {
$charset = ":$charset";
if ($charset =~ m/utf8/) {
$charset = ":utf8";
}
elsif ($charset) {
eval { require Encode }
@@ -7343,9 +7343,11 @@ sub do_with_retries {
$success = $OUT_OF_RETRIES;
}
$get_sth->finish;
if ( $dst && $dst->{dbh} ) {
trace('rollback', sub {
$dst->{dbh}->rollback;
});
}
trace('rollback', sub {
$src->{dbh}->rollback;
});

View File

@@ -957,9 +957,9 @@ collect_mysql_processlist () {
}
collect_mysql_users () {
$CMD_MYSQL $EXT_ARGV -ss -e 'SELECT COUNT(*), SUM(user=""), SUM(password=""), SUM(password NOT LIKE "*%") FROM mysql.user' 2>/dev/null
$CMD_MYSQL $EXT_ARGV -ss -e "SELECT COUNT(*), SUM(user=''), SUM(password=''), SUM(password NOT LIKE '*%') FROM mysql.user" 2>/dev/null
if [ "$?" -ne 0 ]; then
$CMD_MYSQL $EXT_ARGV -ss -e 'SELECT COUNT(*), SUM(user=""), SUM(authentication_string=""), SUM(authentication_string NOT LIKE "*%") FROM mysql.user WHERE account_locked <> "Y" AND password_expired <> "Y" AND authentication_string <> ""' 2>/dev/null
$CMD_MYSQL $EXT_ARGV -ss -e "SELECT COUNT(*), SUM(user=''), SUM(authentication_string=''), SUM(authentication_string NOT LIKE '*%') FROM mysql.user WHERE account_locked <> 'Y' AND password_expired <> 'Y' AND authentication_string <> ''" 2>/dev/null
fi
}
@@ -989,7 +989,7 @@ collect_internal_vars () {
local mysqld_executables="${1:-""}"
local FNV_64=""
if $CMD_MYSQL $EXT_ARGV -e 'SELECT FNV_64("a")' >/dev/null 2>&1; then
if $CMD_MYSQL $EXT_ARGV -e "SELECT FNV_64('a')" >/dev/null 2>&1; then
FNV_64="Enabled";
else
FNV_64="Unknown";
@@ -1035,7 +1035,7 @@ collect_internal_vars () {
}
collect_keyring_plugins() {
$CMD_MYSQL $EXT_ARGV --table -ss -e 'SELECT PLUGIN_NAME, PLUGIN_STATUS FROM INFORMATION_SCHEMA.PLUGINS WHERE PLUGIN_NAME LIKE "keyring%";'
$CMD_MYSQL $EXT_ARGV --table -ss -e "SELECT PLUGIN_NAME, PLUGIN_STATUS FROM INFORMATION_SCHEMA.PLUGINS WHERE PLUGIN_NAME LIKE 'keyring%';"
}
collect_encrypted_tables() {

View File

@@ -3470,11 +3470,29 @@ sub check_table {
}
my ($dbh, $db, $tbl) = @args{@required_args};
my $q = $self->{Quoter} || 'Quoter';
$self->{check_table_error} = undef;
my $lctn_sql = 'SELECT @@lower_case_table_names';
PTDEBUG && _d($lctn_sql);
my $lower_case_table_names;
eval { ($lower_case_table_names) = $dbh->selectrow_array($lctn_sql); };
if ( $EVAL_ERROR ) {
PTDEBUG && _d($EVAL_ERROR);
$self->{check_table_error} = $EVAL_ERROR;
return 0;
}
PTDEBUG && _d("lower_case_table_names=$lower_case_table_names");
if ($lower_case_table_names > 0) {
PTDEBUG && _d("MySQL uses case-insensitive lookup, converting '$tbl' to lowercase");
$tbl = lc $tbl;
}
my $db_tbl = $q->quote($db, $tbl);
PTDEBUG && _d('Checking', $db_tbl);
$self->{check_table_error} = undef;
my $sql = "SHOW TABLES FROM " . $q->quote($db)
. ' LIKE ' . $q->literal_like($tbl);
PTDEBUG && _d($sql);
@@ -8481,7 +8499,7 @@ my $term_readkey = eval {
use sigtrap 'handler', \&sig_int, 'normal-signals';
my $plugin;
my $exit_status = 0;
my $oktorun = 1;
my $dont_interrupt_now = 0;
@@ -8535,6 +8553,9 @@ sub _die {
$exit_status ||= 255;
chomp ($msg);
print "$msg\n";
if ( $plugin && $plugin->can('before_die') ) {
$plugin->before_die(exit_status => $exit_status);
}
exit $exit_status;
}
@@ -8853,7 +8874,7 @@ sub main {
# ########################################################################
# Create --plugin.
# ########################################################################
my $plugin;
if ( my $file = $o->get('plugin') ) {
_die("--plugin file $file does not exist", INVALID_PLUGIN_FILE) unless -f $file;
eval {
@@ -8923,13 +8944,17 @@ sub main {
for my $slave (@$slaves) {
my $is_skip = 0;
for my $slave_to_skip (@$slaves_to_skip) {
if ($slave->{dsn}->{h} eq $slave_to_skip->{h} && $slave->{dsn}->{P} eq $slave_to_skip->{P}) {
if ( $slave->{dsn}->{h} eq $slave_to_skip->{h} ) {
my $skip_slave_port = defined($slave_to_skip->{P})
? $slave_to_skip->{P} : '3306';
if ( ($slave->{dsn}->{P} eq $skip_slave_port) ) {
print "Skipping slave " . $slave->description() . "\n";
$is_skip = 1;
$slave->{dbh}->disconnect();
last;
}
}
}
if (!$is_skip) {
push @$filtered_slaves, $slave;
}
@@ -9590,6 +9615,9 @@ sub main {
$cxn->dbh()->do($sql);
};
if ( $EVAL_ERROR ) {
if ( $plugin && $plugin->can('before_die') ) {
$plugin->before_die(exit_status => $EVAL_ERROR);
}
# this is trapped by a signal handler. Don't replace it with _die
die "Error altering new table $new_tbl->{name}: $EVAL_ERROR\n";
}
@@ -10172,6 +10200,10 @@ sub main {
1 while $nibble_iter->next();
};
if ( $EVAL_ERROR ) {
if ( $plugin && $plugin->can('before_die') ) {
$plugin->before_die(exit_status => $EVAL_ERROR);
}
die ts("Error copying rows from $orig_tbl->{name} to "
. "$new_tbl->{name}: $EVAL_ERROR");
}
@@ -11175,7 +11207,7 @@ sub determine_alter_fk_method {
return ''; # $alter_fk_method can't be undef
}
# The rebuild_constraints method is the default becuase it's safer
# The rebuild_constraints method is the default because it's safer
# and doesn't cause the orig table to go missing for a moment.
my $method = 'rebuild_constraints';
@@ -11630,7 +11662,7 @@ sub random_suffix {
# duplicate_trigger: If set, it will create the trigger on the new table
# with a random string as a trigger name suffix.
# It will also not drop the original trigger.
# This is usefull when creating a temporary trigger for testing
# This is useful when creating a temporary trigger for testing
# purposes or if --no-swap-tables AND --no-drop-new-table was
# specified along with --preserve-triggers. In this case,
# since the original table and triggers are not going to be
@@ -13197,6 +13229,7 @@ These hooks, in this order, are called if defined:
before_drop_old_table
after_drop_old_table
before_drop_triggers
before_die
before_exit
get_slave_lag
@@ -13313,6 +13346,11 @@ Here's a plugin file template for all hooks:
print "PLUGIN before_drop_triggers\n";
}
sub before_die {
my ($self, %args) = @_;
print "PLUGIN before_die\n";
}
sub before_exit {
my ($self, %args) = @_;
print "PLUGIN before_exit\n";

View File

@@ -624,6 +624,7 @@ aggregate_stacktrace() {
}
else {
targ = \$2;
tfile= \$NF;
}
# get rid of long symbol names such as 'pthread_cond_wait@@GLIBC_2.3.2'
if ( targ ~ /@@/ ) {

View File

@@ -8067,6 +8067,7 @@ override query_report => sub {
: undef;
my $fingerprint = substr($item, 0, $self->max_fingerprint_length);
my $checksum = make_checksum($item);
my $explain = $self->explain_report($sample->{arg}, $sample->{db});
my $class = {
checksum => $checksum,
fingerprint => $fingerprint,
@@ -8078,6 +8079,8 @@ override query_report => sub {
query => substr($sample->{arg}, 0, $self->max_query_length),
ts => $sample->{ts} ? parse_timestamp($sample->{ts}) : undef,
Query_time => $sample->{Query_time},
$explain ?
( explain => $explain ): (),
},
),
};

View File

@@ -10653,11 +10653,13 @@ sub main {
for my $slave_to_skip (@$slaves_to_skip) {
my $h_eq_h = $slave->{dsn}->{h} eq $slave_to_skip->{h};
my $p_eq_p;
if (defined($slave->{dsn}->{P}) || defined($slave_to_skip->{P})) {
$p_eq_p = $slave->{dsn}->{P} eq $slave_to_skip->{P};
} else {
if (!defined($slave->{dsn}->{P}) && !defined($slave_to_skip->{P}) ) {
PTDEBUG && _d("Both port DSNs are undefined, setting p_eq_p to true");
$p_eq_p = 1;
} else {
my $skip_slave_port = defined($slave_to_skip->{P})
? $slave_to_skip->{P} : '3306';
$p_eq_p = $slave->{dsn}->{P} eq $skip_slave_port;
}
if ($h_eq_h && $p_eq_p) {
$found=1;
@@ -10955,11 +10957,11 @@ sub main {
# the user does --chunk-size-limit=0 to disable the 1st, documented
# purpose because, apparently, they're using non-unique indexes and
# they don't care about potentially large chunks. But disabling the
# 1st purpose adversely affects the 2nd purpose becuase 0 * the chunk size
# 1st purpose adversely affects the 2nd purpose because 0 * the chunk size
# will always be zero, so tables will only be single-chunked if EXPLAIN
# says there are 0 rows, but sometimes EXPLAIN says there is 1 row
# even when the table is empty. This wouldn't matter except that nibbling
# an empty table doesn't currently work becuase there are no boundaries,
# an empty table doesn't currently work because there are no boundaries,
# so no checksum is written for the empty table. To fix this and
# preserve the two purposes of this option, usages of the 2nd purpose
# do || 1 so the limit is never 0 and empty tables are single-chunked.

View File

@@ -86,8 +86,8 @@ pygments_style = 'sphinx'
# A list of ignored prefixes for module index sorting.
#modindex_common_prefix = []
extlinks = {'jirabug': ('https://jira.percona.com/browse/%s', ''),
'lpbug': ('https://bugs.launchpad.net/percona-toolkit/+bug/%s', '#')}
extlinks = {'jirabug': ('https://jira.percona.com/browse/%s', '%s'),
'lpbug': ('https://bugs.launchpad.net/percona-toolkit/+bug/%s', '#%s')}
# -- Options for HTML output ---------------------------------------------------
# The theme to use for HTML and HTML Help pages. See the documentation for

24
go.mod
View File

@@ -7,12 +7,10 @@ require (
github.com/Ladicle/tabwriter v1.0.0
github.com/Masterminds/semver v1.5.0
github.com/alecthomas/kingpin v2.2.6+incompatible
github.com/alecthomas/kong v0.8.0
github.com/davecgh/go-spew v1.1.1
github.com/alecthomas/kong v0.8.1
github.com/go-ini/ini v1.67.0
github.com/golang/mock v1.6.0
github.com/google/go-cmp v0.5.9
github.com/google/uuid v1.3.1
github.com/google/uuid v1.4.0
github.com/hashicorp/go-version v1.6.0
github.com/howeyc/gopass v0.0.0-20210920133722-c8aef6fb66ef
github.com/lib/pq v1.10.9
@@ -25,13 +23,11 @@ require (
github.com/shirou/gopsutil v3.21.11+incompatible
github.com/sirupsen/logrus v1.9.3
github.com/stretchr/testify v1.8.4
go.mongodb.org/mongo-driver v1.12.1
golang.org/x/crypto v0.13.0
go.mongodb.org/mongo-driver v1.13.0
golang.org/x/crypto v0.15.0
golang.org/x/exp v0.0.0-20230321023759-10a507213a29
gopkg.in/mgo.v2 v2.0.0-20190816093944-a6b53ec6cb22
gopkg.in/yaml.v2 v2.4.0
k8s.io/api v0.28.2
k8s.io/utils v0.0.0-20230406110748-d93618cff8a2
k8s.io/api v0.28.4
)
require (
@@ -56,14 +52,14 @@ require (
github.com/xdg-go/stringprep v1.0.4 // indirect
github.com/youmark/pkcs8 v0.0.0-20201027041543-1326539a0a0a // indirect
github.com/yusufpapurcu/wmi v1.2.2 // indirect
golang.org/x/net v0.13.0 // indirect
golang.org/x/net v0.17.0 // indirect
golang.org/x/sync v0.1.0 // indirect
golang.org/x/sys v0.12.0 // indirect
golang.org/x/term v0.12.0 // indirect
golang.org/x/text v0.13.0 // indirect
golang.org/x/sys v0.14.0 // indirect
golang.org/x/term v0.14.0 // indirect
golang.org/x/text v0.14.0 // indirect
gopkg.in/inf.v0 v0.9.1 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
k8s.io/apimachinery v0.28.2 // indirect
k8s.io/apimachinery v0.28.4 // indirect
k8s.io/klog/v2 v2.100.1 // indirect
sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect
sigs.k8s.io/structured-merge-diff/v4 v4.2.3 // indirect

40
go.sum
View File

@@ -8,8 +8,8 @@ github.com/alecthomas/assert/v2 v2.1.0 h1:tbredtNcQnoSd3QBhQWI7QZ3XHOVkw1Moklp2o
github.com/alecthomas/assert/v2 v2.1.0/go.mod h1:b/+1DI2Q6NckYi+3mXyH3wFb8qG37K/DuK80n7WefXA=
github.com/alecthomas/kingpin v2.2.6+incompatible h1:5svnBTFgJjZvGKyYBtMB0+m5wvrbUHiqye8wRJMlnYI=
github.com/alecthomas/kingpin v2.2.6+incompatible/go.mod h1:59OFYbFVLKQKq+mqrL6Rw5bR0c3ACQaawgXx0QYndlE=
github.com/alecthomas/kong v0.8.0 h1:ryDCzutfIqJPnNn0omnrgHLbAggDQM2VWHikE1xqK7s=
github.com/alecthomas/kong v0.8.0/go.mod h1:n1iCIO2xS46oE8ZfYCNDqdR0b0wZNrXAIAqro/2132U=
github.com/alecthomas/kong v0.8.1 h1:acZdn3m4lLRobeh3Zi2S2EpnXTd1mOL6U7xVml+vfkY=
github.com/alecthomas/kong v0.8.1/go.mod h1:n1iCIO2xS46oE8ZfYCNDqdR0b0wZNrXAIAqro/2132U=
github.com/alecthomas/repr v0.1.0 h1:ENn2e1+J3k09gyj2shc0dHr/yjaWSHRlrJ4DPMevDqE=
github.com/alecthomas/repr v0.1.0/go.mod h1:2kn6fqh/zIyPLmm3ugklbEi5hg5wS435eygvNfaDQL8=
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751 h1:JYp7IbQjafoB+tBA3gMyHYHrpOtNuDiK/uB5uXxq5wM=
@@ -41,8 +41,8 @@ github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeN
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0=
github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/uuid v1.3.1 h1:KjJaJ9iWZ3jOFZIf1Lqf4laDRCasjl0BCmnEGxkdLb4=
github.com/google/uuid v1.3.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.4.0 h1:MtMxsa51/r9yyhkyLsVeVt0B+BGQZzpQiTQ4eHZ8bc4=
github.com/google/uuid v1.4.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/hashicorp/go-version v1.6.0 h1:feTTfFNnjP967rlCxM/I9g701jU+RN74YKx2mOkIeek=
github.com/hashicorp/go-version v1.6.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
github.com/hexops/gotextdiff v1.0.3 h1:gitA9+qJrrTCsiCl7+kh75nPqQt1cx4ZkudSTLoUqJM=
@@ -120,16 +120,16 @@ github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
github.com/yusufpapurcu/wmi v1.2.2 h1:KBNDSne4vP5mbSWnJbO+51IMOXJB67QiYCSBrubbPRg=
github.com/yusufpapurcu/wmi v1.2.2/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0=
go.mongodb.org/mongo-driver v1.12.1 h1:nLkghSU8fQNaK7oUmDhQFsnrtcoNy7Z6LVFKsEecqgE=
go.mongodb.org/mongo-driver v1.12.1/go.mod h1:/rGBTebI3XYboVmgz+Wv3Bcbl3aD0QF9zl6kDDw18rQ=
go.mongodb.org/mongo-driver v1.13.0 h1:67DgFFjYOCMWdtTEmKFpV3ffWlFnh+CYZ8ZS/tXWUfY=
go.mongodb.org/mongo-driver v1.13.0/go.mod h1:/rGBTebI3XYboVmgz+Wv3Bcbl3aD0QF9zl6kDDw18rQ=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20200302210943-78000ba7a073/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/crypto v0.13.0 h1:mvySKfSWJ+UKUii46M40LOvyWfN0s2U+46/jDd0e6Ck=
golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc=
golang.org/x/crypto v0.15.0 h1:frVn1TEaCEaZcn3Tmd7Y2b5KKPaZ+I32Q2OA3kYp5TA=
golang.org/x/crypto v0.15.0/go.mod h1:4ChreQoLWfG3xLDer1WdlH5NdlQ3+mwnQq1YTKY+72g=
golang.org/x/exp v0.0.0-20230321023759-10a507213a29 h1:ooxPy7fPvB4kwsA2h+iBNHkAbp/4JxTSwCmvdjEYmug=
golang.org/x/exp v0.0.0-20230321023759-10a507213a29/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc=
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
@@ -144,8 +144,8 @@ golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/net v0.13.0 h1:Nvo8UFsZ8X3BhAC9699Z1j7XQ3rsZnUUm7jfBEk1ueY=
golang.org/x/net v0.13.0/go.mod h1:zEVYFnQC7m/vmpQFELhcD1EWkZlX69l4oqgmer6hfKA=
golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM=
golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
@@ -168,20 +168,20 @@ golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.12.0 h1:CM0HF96J0hcLAwsHPJZjfdNzs0gftsLfgKt57wWHJ0o=
golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.14.0 h1:Vz7Qs629MkJkGyHxUlRHizWJRG2j8fbQKjELVSNhy7Q=
golang.org/x/sys v0.14.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.12.0 h1:/ZfYdc3zq+q02Rv9vGqTeSItdzZTSNDmfTi0mBAuidU=
golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU=
golang.org/x/term v0.14.0 h1:LGK9IlZ8T9jvdy6cTdfKUCltatMFOehAQo9SRC46UQ8=
golang.org/x/term v0.14.0/go.mod h1:TySc+nGkYR6qt8km8wUhuFRTVSMIX3XPR58y2lC8vww=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ=
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k=
golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
@@ -206,10 +206,10 @@ gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
k8s.io/api v0.28.2 h1:9mpl5mOb6vXZvqbQmankOfPIGiudghwCoLl1EYfUZbw=
k8s.io/api v0.28.2/go.mod h1:RVnJBsjU8tcMq7C3iaRSGMeaKt2TWEUXcpIt/90fjEg=
k8s.io/apimachinery v0.28.2 h1:KCOJLrc6gu+wV1BYgwik4AF4vXOlVJPdiqn0yAWWwXQ=
k8s.io/apimachinery v0.28.2/go.mod h1:RdzF87y/ngqk9H4z3EL2Rppv5jj95vGS/HaFXrLDApU=
k8s.io/api v0.28.4 h1:8ZBrLjwosLl/NYgv1P7EQLqoO8MGQApnbgH8tu3BMzY=
k8s.io/api v0.28.4/go.mod h1:axWTGrY88s/5YE+JSt4uUi6NMM+gur1en2REMR7IRj0=
k8s.io/apimachinery v0.28.4 h1:zOSJe1mc+GxuMnFzD4Z/U1wst50X28ZNsn5bhgIIao8=
k8s.io/apimachinery v0.28.4/go.mod h1:wI37ncBvfAoswfq626yPTe6Bz1c22L7uaJ8dho83mgg=
k8s.io/klog/v2 v2.100.1 h1:7WCHKK6K8fNhTqfBhISHQ97KrnJNFZMcQvKp7gP/tmg=
k8s.io/klog/v2 v2.100.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0=
k8s.io/utils v0.0.0-20230406110748-d93618cff8a2 h1:qY1Ad8PODbnymg2pRbkyMT/ylpTrCM8P2RJ0yroCyIk=

View File

@@ -241,6 +241,7 @@ override query_report => sub {
: undef;
my $fingerprint = substr($item, 0, $self->max_fingerprint_length);
my $checksum = make_checksum($item);
my $explain = $self->explain_report($sample->{arg}, $sample->{db});
my $class = {
checksum => $checksum,
fingerprint => $fingerprint,
@@ -252,6 +253,8 @@ override query_report => sub {
query => substr($sample->{arg}, 0, $self->max_query_length),
ts => $sample->{ts} ? parse_timestamp($sample->{ts}) : undef,
Query_time => $sample->{Query_time},
$explain ?
( explain => $explain ): (),
},
),
};

View File

@@ -327,11 +327,33 @@ sub check_table {
}
my ($dbh, $db, $tbl) = @args{@required_args};
my $q = $self->{Quoter} || 'Quoter';
$self->{check_table_error} = undef;
# https://dev.mysql.com/doc/refman/8.0/en/identifier-case-sensitivity.html
# MySQL may use use case-insensitive table lookup, this is controller by
# @@lower_case_table_names. 0 means case sensitive search, 1 or 2 means
# case insensitive lookup.
my $lctn_sql = 'SELECT @@lower_case_table_names';
PTDEBUG && _d($lctn_sql);
my $lower_case_table_names;
eval { ($lower_case_table_names) = $dbh->selectrow_array($lctn_sql); };
if ( $EVAL_ERROR ) {
PTDEBUG && _d($EVAL_ERROR);
$self->{check_table_error} = $EVAL_ERROR;
return 0;
}
PTDEBUG && _d("lower_case_table_names=$lower_case_table_names");
if ($lower_case_table_names > 0) {
PTDEBUG && _d("MySQL uses case-insensitive lookup, converting '$tbl' to lowercase");
$tbl = lc $tbl;
}
my $db_tbl = $q->quote($db, $tbl);
PTDEBUG && _d('Checking', $db_tbl);
$self->{check_table_error} = undef;
my $sql = "SHOW TABLES FROM " . $q->quote($db)
. ' LIKE ' . $q->literal_like($tbl);
PTDEBUG && _d($sql);

View File

@@ -135,9 +135,9 @@ collect_mysql_processlist () {
collect_mysql_users () {
# The where clause has been added to skip listing MySQL 8+ roles as users.
# ROLES are locked accounts, without passwords and expired.
$CMD_MYSQL $EXT_ARGV -ss -e 'SELECT COUNT(*), SUM(user=""), SUM(password=""), SUM(password NOT LIKE "*%") FROM mysql.user' 2>/dev/null
$CMD_MYSQL $EXT_ARGV -ss -e "SELECT COUNT(*), SUM(user=''), SUM(password=''), SUM(password NOT LIKE '*%') FROM mysql.user" 2>/dev/null
if [ "$?" -ne 0 ]; then
$CMD_MYSQL $EXT_ARGV -ss -e 'SELECT COUNT(*), SUM(user=""), SUM(authentication_string=""), SUM(authentication_string NOT LIKE "*%") FROM mysql.user WHERE account_locked <> "Y" AND password_expired <> "Y" AND authentication_string <> ""' 2>/dev/null
$CMD_MYSQL $EXT_ARGV -ss -e "SELECT COUNT(*), SUM(user=''), SUM(authentication_string=''), SUM(authentication_string NOT LIKE '*%') FROM mysql.user WHERE account_locked <> 'Y' AND password_expired <> 'Y' AND authentication_string <> ''" 2>/dev/null
fi
}
@@ -168,7 +168,7 @@ collect_internal_vars () {
local mysqld_executables="${1:-""}"
local FNV_64=""
if $CMD_MYSQL $EXT_ARGV -e 'SELECT FNV_64("a")' >/dev/null 2>&1; then
if $CMD_MYSQL $EXT_ARGV -e "SELECT FNV_64('a')" >/dev/null 2>&1; then
FNV_64="Enabled";
else
FNV_64="Unknown";
@@ -215,7 +215,7 @@ collect_internal_vars () {
}
collect_keyring_plugins() {
$CMD_MYSQL $EXT_ARGV --table -ss -e 'SELECT PLUGIN_NAME, PLUGIN_STATUS FROM INFORMATION_SCHEMA.PLUGINS WHERE PLUGIN_NAME LIKE "keyring%";'
$CMD_MYSQL $EXT_ARGV --table -ss -e "SELECT PLUGIN_NAME, PLUGIN_STATUS FROM INFORMATION_SCHEMA.PLUGINS WHERE PLUGIN_NAME LIKE 'keyring%';"
}
collect_encrypted_tables() {

View File

@@ -22,7 +22,7 @@ pkgs = $(shell find . -type d -name "pt-*" -exec basename {} \;)
# VERSION ?=$(shell git describe --abbrev=0) doesn't always work here, need to use git log
VERSION ?=$(shell git log --no-walk --tags --pretty="%H %d" --decorate=short | head -n1 | awk -F'[, $(CP)]' '{ print $$4; }')
BUILD=$(BUILD_DATE)
GOVERSION=$(shell go version | cut --delimiter=" " -f3)
GOVERSION=$(shell go version | cut -d " " -f3)
GOUTILSDIR ?= $(GOPATH)/bin
FILES = $(shell find . -type f -name '*.go' -not -path "./vendor/*")
PREFIX=$(shell pwd)
@@ -127,24 +127,36 @@ env-down: env ## Clean-up MongoDB docker containers cluster
docker-compose down -v
rm .env
linux-amd64: ## Build Mongo tools for linux-amd64.
linux-amd64: ## Build Go tools for linux-amd64.
@echo "Building linux/amd64 binaries in ${BIN_DIR} as version ${VERSION}"
@cd ${TOP_DIR} && go get ./...
@$(foreach pkg,$(pkgs),rm -f ${BIN_DIR}/$(pkg) 2> /dev/null;)
@$(foreach pkg,$(pkgs),GOOS=linux GOARCH=amd64 go build -ldflags ${LDFLAGS} -o ${BIN_DIR}/$(pkg) ./$(pkg);)
linux-386: ## Build Mongo tools for linux-386
linux-386: ## Build Go tools for linux-386
@echo "Building linux/386 binaries in ${BIN_DIR} as version ${VERSION}"
@cd ${TOP_DIR} && go get ./...
@$(foreach pkg,$(pkgs),rm -f ${BIN_DIR}/$(pkg) 2> /dev/null;)
@$(foreach pkg,$(pkgs),GOOS=linux GOARCH=386 go build -ldflags ${LDFLAGS} -o ${BIN_DIR}/$(pkg) ./$(pkg);)
darwin-amd64: ## Build Mongo tools for darwin-amd64 (MacOS)
darwin-amd64: ## Build Go tools for darwin-amd64 (MacOS)
@echo "Building darwin/amd64 binaries in ${BIN_DIR} as version ${VERSION}"
@cd ${TOP_DIR} && go get ./...
@$(foreach pkg,$(pkgs),rm -f ${BIN_DIR}/$(pkg) 2> /dev/null;)
@$(foreach pkg,$(pkgs),GOOS=darwin GOARCH=amd64 go build -ldflags ${LDFLAGS} -o ${BIN_DIR}/$(pkg) ./$(pkg);)
darwin-arm64: ## Build Go tools for darwin-arm64 (MacOS)
@echo "Building darwin/arm64 binaries in ${BIN_DIR} as version ${VERSION}"
@cd ${TOP_DIR} && go get ./...
@$(foreach pkg,$(pkgs),rm -f ${BIN_DIR}/$(pkg) 2> /dev/null;)
@$(foreach pkg,$(pkgs),GOOS=darwin GOARCH=arm64 go build -ldflags ${LDFLAGS} -o ${BIN_DIR}/$(pkg) ./$(pkg);)
build:
@echo "Building binaries in ${BIN_DIR} as version ${VERSION}"
@cd ${TOP_DIR} && go get ./...
@$(foreach pkg,$(pkgs),rm -f ${BIN_DIR}/$(pkg) 2> /dev/null;)
@$(foreach pkg,$(pkgs),go build -ldflags ${LDFLAGS} -o ${BIN_DIR}/$(pkg) ./$(pkg);)
style: ## Check code style
@echo ">> checking code style"
@! gofmt -d $(shell find . -path ./vendor -prune -o -name '*.go' -print) | grep '^'

View File

@@ -129,14 +129,14 @@ func TestOverrideConfig(t *testing.T) {
}
func TestDefaultFiles(t *testing.T) {
user, _ := user.Current()
current, _ := user.Current()
toolname := "pt-testing"
want := []string{
"/etc/percona-toolkit/percona-toolkit.conf",
fmt.Sprintf("/etc/percona-toolkit/%s.conf", toolname),
fmt.Sprintf("%s/.percona-toolkit.conf", user.HomeDir),
fmt.Sprintf("%s/.%s.conf", user.HomeDir, toolname),
fmt.Sprintf("%s/.percona-toolkit.conf", current.HomeDir),
fmt.Sprintf("%s/.%s.conf", current.HomeDir, toolname),
}
got, err := DefaultConfigFiles(toolname)

View File

@@ -37,7 +37,7 @@ type Security struct {
KeyFile string `bson:"keyFile"`
ClusterAuthMode string `bson:"clusterAuthMode"`
Authorization string `bson:"authorization"`
JavascriptEnabled bool `bson:javascriptEnabled"`
JavascriptEnabled bool `bson:"javascriptEnabled"`
Sasl struct {
HostName string `bson:"hostName"`
ServiceName string `bson:"serverName"`

View File

@@ -31,7 +31,7 @@ type ServerStatus struct {
type StorageEngine struct {
Name string `bson:"name"`
SupportCommittedREads bool `bson:supportsCommittedReads"`
SupportsCommittedReads bool `bson:"supportsCommittedReads"`
ReadOnly bool `bson:"readOnly"`
Persistent bool `bson:"persistent"`
}

View File

@@ -24,6 +24,7 @@ type Dumper struct {
kubeconfig string
resources []string
filePaths []string
fileContainer string
namespace string
location string
errors string
@@ -124,6 +125,7 @@ func New(location, namespace, resource string, kubeconfig string, forwardport st
"var/lib/mysql/mysqld.post.processing.log",
"var/lib/mysql/auto.cnf",
)
d.fileContainer = "logs"
}
d.resources = resources
d.crType = resource
@@ -272,7 +274,7 @@ func (d *Dumper) DumpCluster() error {
// get individual Logs
location = filepath.Join(d.location, ns.Name, pod.Name)
for _, path := range d.filePaths {
err = d.getIndividualFiles(resourceType(d.crType), ns.Name, pod.Name, path, location, tw)
err = d.getIndividualFiles(ns.Name, pod.Name, path, location, tw)
if err != nil {
d.logError(err.Error(), "get file "+path+" for pod "+pod.Name)
log.Printf("Error: get %s file: %v", path, err)
@@ -370,13 +372,15 @@ type crSecrets struct {
} `json:"spec"`
}
// TODO: check if resource parameter is really needed
func (d *Dumper) getIndividualFiles(resource, namespace string, podName, path, location string, tw *tar.Writer) error {
args := []string{"-n", namespace, "cp", podName + ":" + path, "/dev/stdout"}
func (d *Dumper) getIndividualFiles(namespace string, podName, path, location string, tw *tar.Writer) error {
if len(d.fileContainer) == 0 {
return errors.Errorf("Logs container name is not specified for resource %s in namespace %s", resourceType(d.crType), d.namespace)
}
args := []string{"-n", namespace, "-c", d.fileContainer, "cp", podName + ":" + path, "/dev/stdout"}
output, err := d.runCmd(args...)
if err != nil {
d.logError(err.Error(), args...)
log.Printf("Error: get path %s for resource %s in namespace %s: %v", path, resource, d.namespace, err)
log.Printf("Error: get path %s for resource %s in namespace %s: %v", path, resourceType(d.crType), d.namespace, err)
return addToArchive(location, d.mode, []byte(err.Error()), tw)
}

View File

@@ -0,0 +1,20 @@
package dumper
import (
"testing"
"github.com/stretchr/testify/assert"
)
/*
Unit test for non-existing logs container name error handling
*/
func TestGetIndividualFilesError(t *testing.T) {
d := New("", "", "psmdb", "", "")
err := d.getIndividualFiles("", "", "", "", nil)
assert.Error(t, err)
assert.ErrorContains(t, err, "Logs container name is not specified")
}

View File

@@ -412,15 +412,15 @@ type multiSorter struct {
less []lessFunc
}
// Sort sorts the argument slice according to the less functions passed to OrderedBy.
// Sort sorts the argument slice according to the less functions passed to orderedBy.
func (ms *multiSorter) Sort(queries []stats.QueryStats) {
ms.queries = queries
sort.Sort(ms)
}
// OrderedBy returns a Sorter that sorts using the less functions, in order.
// orderedBy returns a Sorter that sorts using the less functions, in order.
// Call its Sort method to sort the data.
func OrderedBy(less ...lessFunc) *multiSorter {
func orderedBy(less ...lessFunc) *multiSorter {
return &multiSorter{
less: less,
}
@@ -520,7 +520,7 @@ func sortQueries(queries []stats.QueryStats, orderby []string) []stats.QueryStat
sortFuncs = append(sortFuncs, f)
}
OrderedBy(sortFuncs...).Sort(queries)
orderedBy(sortFuncs...).Sort(queries)
return queries
}

67
t/pt-archiver/pt-2064.t Normal file
View File

@@ -0,0 +1,67 @@
#!/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 Time::HiRes qw(time);
use PerconaTest;
use Sandbox;
use Data::Dumper;
require "$trunk/bin/pt-archiver";
my $dp = new DSNParser(opts=>$dsn_opts);
my $sb = new Sandbox(basedir => '/tmp', DSNParser => $dp);
my $master_dbh = $sb->get_dbh_for('master');
my $slave1_dbh = $sb->get_dbh_for('slave1');
if ( !$master_dbh ) {
plan skip_all => 'Cannot connect to sandbox master';
}
elsif ( !$slave1_dbh ) {
plan skip_all => 'Cannot connect to sandbox slave1';
}
my $cnf = "/tmp/12345/my.sandbox.cnf";
my $cmd = "$trunk/bin/pt-archiver";
my @args = qw(--where 1=1);
$sb->create_dbs($master_dbh, ['test']);
$sb->load_file('master', 't/pt-archiver/samples/table1.sql');
$sb->wait_for_slaves();
$master_dbh->do('set global innodb_lock_wait_timeout=1');
$master_dbh->do('begin');
$master_dbh->do('select * from test.table_1 for update;');
my ($output, $exit_val) = full_output(sub {pt_archiver::main(@args, '--source', "D=test,t=table_1,F=$cnf", qw(--purge)) });
is(
$exit_val,
0,
'No rollback on non-existent destination'
);
unlike(
$output,
qr/Can't call method "rollback" on an undefined value/,
'No rollback on non-existent destination'
) or diag($output);
# #############################################################################
# Done.
# #############################################################################
$master_dbh->do('set global innodb_lock_wait_timeout=DEFAULT');
$sb->wipe_clean($master_dbh);
ok($sb->ok(), "Sandbox servers") or BAIL_OUT(__FILE__ . " broke the sandbox");
done_testing;

67
t/pt-archiver/pt-2207.t Normal file
View File

@@ -0,0 +1,67 @@
#!/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-archiver";
my $dp = new DSNParser(opts=>$dsn_opts);
my $sb = new Sandbox(basedir => '/tmp', DSNParser => $dp);
my $dbh = $sb->get_dbh_for('master');
if ( !$dbh ) {
plan skip_all => 'Cannot connect to sandbox master';
}
my $output;
my $exit_val;
my $rows;
my $cnf = "/tmp/12345/my.sandbox.cnf";
my $cmd = "$trunk/bin/pt-archiver";
$sb->create_dbs($dbh, ['test']);
$sb->load_file('master', 't/pt-archiver/samples/table1.sql');
# Archive to a file.
`rm -f archive.test.table_1`;
($output, $exit_val) = full_output(
sub { pt_archiver::main(qw(--where 1=1), "--source", "D=test,t=table_1,F=$cnf", "--file", 'archive.%D.%t', "--set-vars", "sql_mode=ANSI_QUOTES") },
);
is($exit_val,
0,
"SQL Mode ANSI_QUOTES works"
) or diag($output);
is($output, '', 'No output for archiving to a file');
$output = `/tmp/12345/use -N -e "select count(*) from test.table_1"`;
is($output + 0, 0, 'Purged all rows ok');
ok(-f 'archive.test.table_1', 'Archive file written OK');
$output = `cat archive.test.table_1`;
is($output, <<EOF
1\t2\t3\t4
2\t\\N\t3\t4
3\t2\t3\t\\\t
4\t2\t3\t\\
EOF
, 'File has the right stuff');
`rm -f archive.test.table_1`;
# #############################################################################
# Done.
# #############################################################################
diag(`rm -f /tmp/*.table_1`);
$sb->wipe_clean($dbh);
ok($sb->ok(), "Sandbox servers") or BAIL_OUT(__FILE__ . " broke the sandbox");
done_testing;

80
t/pt-archiver/pt-2279.t Normal file
View File

@@ -0,0 +1,80 @@
#!/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 charnames ':full';
use PerconaTest;
use Sandbox;
require "$trunk/bin/pt-archiver";
my $dp = new DSNParser(opts=>$dsn_opts);
my $sb = new Sandbox(basedir => '/tmp', DSNParser => $dp);
my $dbh = $sb->get_dbh_for('master');
if ( !$dbh ) {
plan skip_all => 'Cannot connect to sandbox master';
}
my $output;
my $cnf = "/tmp/12345/my.sandbox.cnf";
my $cmd = "$trunk/bin/pt-archiver";
$sb->wipe_clean($dbh);
$sb->create_dbs($dbh, ['test']);
# Test --bulk-insert
$sb->load_file('master', 't/pt-archiver/samples/pt-2279.sql');
$output = output(
sub { pt_archiver::main(qw(--limit 50 --bulk-insert),
qw(--bulk-delete --where 1=1 --statistics --charset utf8mb4),
'--source', "L=1,D=test,t=table_1,F=$cnf",
'--dest', "t=table_1_dest") },
);
unlike(
$output,
qr/Cannot find encoding "utf8mb4"/,
'Bulk insert does not fail due to missing utf8mb4'
) or diag($output);
# Test --file
$sb->load_file('master', 't/pt-archiver/samples/pt-2279.sql');
$output = output(
sub { pt_archiver::main(qw(--limit 50),
qw(--where 1=1 --statistics --charset utf8mb4),
'--source', "L=1,D=test,t=table_1,F=$cnf",
'--file', '/tmp/%Y-%m-%d-%D_%H:%i:%s.%t') },
);
unlike(
$output,
qr/Cannot find encoding "utf8mb4"/,
'Destination file does not fail due to missing utf8mb4'
) or diag($output);
unlike(
$output,
qr/Cannot open :encoding(utf8mb4)/,
'Destination file can be read if encodin utf8mb4 is used'
) or diag($output);
# #############################################################################
# Done.
# #############################################################################
diag(`rm -f /tmp/*.table_1`);
$sb->wipe_clean($dbh);
ok($sb->ok(), "Sandbox servers") or BAIL_OUT(__FILE__ . " broke the sandbox");
done_testing;
exit;

View File

@@ -0,0 +1,18 @@
DROP TABLE IF EXISTS test.table_1;
DROP TABLE IF EXISTS test.table_1_dest;
SET NAMES utf8mb4;
CREATE TABLE test.table_1 (
id int(11) NOT NULL,
c1 varchar(20) DEFAULT NULL,
PRIMARY KEY (id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
INSERT INTO test.table_1 VALUES(1, 'I love MySQL! 🐬');
CREATE TABLE test.table_1_dest (
id int(11) NOT NULL,
c1 varchar(10) DEFAULT NULL,
PRIMARY KEY (id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

View File

@@ -0,0 +1,60 @@
#!/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 PerconaTest;
use Sandbox;
use DSNParser;
require VersionParser;
use Test::More;
local $ENV{PTDEBUG} = "";
my $dp = new DSNParser(opts=>$dsn_opts);
my $sb = new Sandbox(basedir => '/tmp', DSNParser => $dp);
my $dbh = $sb->get_dbh_for('master');
my $has_keyring_plugin;
if ( !$dbh ) {
plan skip_all => 'Cannot connect to sandbox master';
}
else {
plan tests => 3;
}
my $output;
my $cnf = '/tmp/12345/my.sandbox.cnf';
my ($orig_sql_mode) = $dbh->selectrow_array(q{SELECT @@SQL_MODE});
$dbh->do("SET GLOBAL SQL_MODE='ANSI_QUOTES'");
my $cmd = "$trunk/bin/pt-mysql-summary --sleep 1 -- --defaults-file=$cnf";
$output = `$cmd 2>&1`;
unlike(
$output,
qr/Unknown column 'keyring%' in 'where clause'/s,
"pt-mysql-summary works fine with SQL Mode ANSI_QUOTES"
);
unlike(
$output,
qr/You have an error in your SQL syntax.*wsrep_on/s,
"pt-mysql-summary works fine with PXC and SQL Mode ANSI_QUOTES"
);
# #############################################################################
# Done.
# #############################################################################
$dbh->do("SET GLOBAL SQL_MODE='${orig_sql_mode}'");
$sb->wipe_clean($dbh);
ok($sb->ok(), "Sandbox servers") or BAIL_OUT(__FILE__ . " broke the sandbox");
exit;

View File

@@ -97,6 +97,35 @@ like(
"Security works"
);
#
# SQL Mode ANSI_QUOTES
#
my ($orig_sql_mode) = $master_dbh->selectrow_array(q{SELECT @@SQL_MODE});
$master_dbh->do("SET GLOBAL SQL_MODE='ANSI_QUOTES'");
$out = `$env $trunk/bin/$tool --sleep 1 --databases mysql 2>/dev/null -- --defaults-file=/tmp/12345/my.sandbox.cnf`;
like(
$out,
qr/Database Tables Views SPs Trigs Funcs FKs Partn\s+\Qmysql\E/,
"--databases works with SQL Mode ANSI_QUOTES"
);
like(
$out,
qr/# InnoDB #.*Version.*# MyISAM #/s,
"InnoDB section present with SQL Mode ANSI_QUOTES"
);
like(
$out,
qr/Users \| 2/,
"Security works with SQL Mode ANSI_QUOTES"
);
$master_dbh->do("SET GLOBAL SQL_MODE='${orig_sql_mode}'");
# --read-samples
for my $i (2..9) {
ok(

View File

@@ -696,21 +696,30 @@ SKIP: {
qr/$skipping_str/s,
"--skip-check-slave-lag",
);
}
# Use the same data than the previous test
$master_dbh->do("DROP DATABASE IF EXISTS test");
# Test for skip-check-slave-lag and empty replica port
# Use the same data than the previous test
$master_dbh->do("DROP DATABASE IF EXISTS test");
$sb->load_file('master', "$sample/bug-1613915.sql");
$output = output(
$sb->load_file('master', "$sample/bug-1613915.sql");
$output = output(
sub { pt_online_schema_change::main(@args, "$master_dsn,D=test,t=o1",
'--execute',
'--alter', "ADD COLUMN c INT",
'--chunk-size', '10',
'--skip-check-slave-lag', "h=127.0.0.1,P=".$sb->port_for('slave1'),
'--skip-check-slave-lag', "h=127.0.0.1",
),
},
);
stderr => 1,
);
unlike(
$output,
qr/Use of uninitialized value.*/,
'No syntax error if port is missed in --skip-check-slave-lag DSN',
) or diag($output);
}
# #############################################################################
# Done.

View File

@@ -0,0 +1,79 @@
#!/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 Time::HiRes qw(sleep);
use PerconaTest;
use Sandbox;
require "$trunk/bin/pt-online-schema-change";
require VersionParser;
my $dp = new DSNParser(opts=>$dsn_opts);
my $sb = new Sandbox(basedir => '/tmp', DSNParser => $dp);
my $master_dbh = $sb->get_dbh_for('master');
if ( !$master_dbh ) {
plan skip_all => 'Cannot connect to sandbox master';
}
my @args = qw(--set-vars innodb_lock_wait_timeout=3);
my $output = "";
my $dsn = "h=127.1,P=12345,u=msandbox,p=msandbox";
my $exit = 0;
my $sample = "t/pt-online-schema-change/samples";
my $lower_case_table_names = $master_dbh->selectrow_array('SELECT @@lower_case_table_names');
if ( $lower_case_table_names == 0) {
# Preparing test setup on Linux
diag(`$trunk/sandbox/stop-sandbox 12348 >/dev/null`);
diag(`EXTRA_DEFAULTS_FILE="$trunk/t/pt-online-schema-change/samples/lower_case_table_names_1.cnf" $trunk/sandbox/start-sandbox master 12348 >/dev/null`);
$master_dbh = $sb->get_dbh_for('master1');
$dsn = "h=127.1,P=12348,u=msandbox,p=msandbox";
$sb->load_file('master1', "$sample/basic_no_fks_innodb.sql");
} else {
$sb->load_file('master', "$sample/basic_no_fks_innodb.sql");
}
($output, $exit) = full_output(
sub { pt_online_schema_change::main(@args, "$dsn,D=pt_osc,t=T",
'--alter', 'drop column d', '--execute') }
);
like(
$output,
qr/Successfully altered/,
"Table is altered using capital name 'T'"
) or diag($output);
my $ddl = $master_dbh->selectrow_arrayref("show create table pt_osc.T");
unlike(
$ddl->[1],
qr/^\s+["`]d["`]/m,
"'D' column is dropped"
);
is(
$exit,
0,
"Exit 0"
);
# #############################################################################
# Done.
# #############################################################################
diag(`$trunk/sandbox/stop-sandbox 12348 >/dev/null`);
$master_dbh = $sb->get_dbh_for('master');
$sb->wipe_clean($master_dbh);
ok($sb->ok(), "Sandbox servers") or BAIL_OUT(__FILE__ . " broke the sandbox");
done_testing;

View File

@@ -0,0 +1,114 @@
#!/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');
if ( !$master_dbh ) {
plan skip_all => 'Cannot connect to sandbox master';
}
# 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");
# Should be greater than chunk-size and big enough, so plugin will trigger few times
my $num_rows = 5000;
diag("Loading $num_rows into the table. This might take some time.");
diag(`util/mysql_random_data_load --host=127.0.0.1 --port=12345 --user=msandbox --password=msandbox pt_osc t $num_rows`);
($output, $exit_status) = full_output(
sub { pt_online_schema_change::main(@args,
"$master_dsn,D=pt_osc,t=t",
"--alter", "CHARACTER SET utf9",
'--plugin', "$plugin/before_die.pm",
'--execute') },
);
like(
$output,
qr/PLUGIN before_die/s,
'Plugin before_die called for invalid ALTER command'
);
like(
$output,
qr/Exit status: .*Unknown character set: 'utf9'/s,
'Expected exit status for invalid ALTER command'
);
($output, $exit_status) = full_output(
sub { pt_online_schema_change::main(@args,
"$master_dsn,D=pt_osc,t=t",
"--alter", "ENGINE=InnoDB",
'--plugin', "$plugin/before_die_after_nibble.pm",
'--execute') },
);
like(
$output,
qr/PLUGIN before_die/s,
'Plugin before_die called for error while copying nibble'
);
like(
$output,
qr/Exit status: .*You have an error in your SQL syntax/s,
'Expected exit status for error while copying nibble'
);
($output, $exit_status) = full_output(
sub { pt_online_schema_change::main(@args,
"$master_dsn,D=pt_osc,t=t",
"--alter", "ENGINE=InnoDB",
'--plugin', "$plugin/before_die_after_create.pm",
'--execute') },
);
like(
$output,
qr/PLUGIN before_die/s,
'Plugin before_die called for _die call'
);
like(
$output,
qr/Exit status: 4/s,
'Expected exit status for table definition error handled in the _die call'
);
# #############################################################################
# Done.
# #############################################################################
$sb->wipe_clean($master_dbh);
ok($sb->ok(), "Sandbox servers") or BAIL_OUT(__FILE__ . " broke the sandbox");
done_testing;

View File

@@ -40,9 +40,13 @@ my $master_dsn = 'h=127.0.0.1,P=12345,u=msandbox,p=msandbox';
my $slave_dsn1 = 'h=127.0.0.1,P=12346,u=msandbox,p=msandbox';
my $slave_dsn2 = 'h=127.0.0.1,P=12347,u=msandbox,p=msandbox';
my $sample = "t/pt-online-schema-change/samples";
my ($orig_master_info_repository) = $slave_dbh1->selectrow_array(q{SELECT @@master_info_repository});
my ($orig_relay_log_info_repository) = $slave_dbh1->selectrow_array(q{SELECT @@relay_log_info_repository});
$slave_dbh1->do("stop slave");
$slave_dbh1->do("reset slave all");
$slave_dbh1->do("SET GLOBAL master_info_repository='TABLE'");
$slave_dbh1->do("SET GLOBAL relay_log_info_repository='TABLE'");
$slave_dbh1->do("CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_PORT=12345, MASTER_USER = 'msandbox', MASTER_PASSWORD='msandbox' FOR CHANNEL 'channel1';");
$slave_dbh1->do("start slave");
@@ -74,6 +78,8 @@ like(
$slave_dbh1->do('STOP SLAVE');
$master_dbh->do("RESET MASTER");
$slave_dbh1->do('RESET SLAVE ALL');
$slave_dbh1->do("SET GLOBAL master_info_repository='${orig_master_info_repository}'");
$slave_dbh1->do("SET GLOBAL relay_log_info_repository='${orig_relay_log_info_repository}'");
$slave_dbh1->do("CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_PORT=12345, MASTER_USER = 'msandbox', MASTER_PASSWORD='msandbox';");
$slave_dbh1->do('START SLAVE');

View File

@@ -0,0 +1,2 @@
[mysqld]
lower_case_table_names=1

View File

@@ -96,6 +96,11 @@ sub before_drop_triggers {
print "PLUGIN before_drop_triggers\n";
}
sub before_die {
my ($self, %args) = @_;
print "PLUGIN before_die\n";
}
sub before_exit {
my ($self, %args) = @_;
print "PLUGIN before_exit\n";

View File

@@ -0,0 +1,20 @@
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 before_die {
my ($self, %args) = @_;
print "PLUGIN before_die\n";
print "Exit status: $args{exit_status}\n";
}
1;

View File

@@ -0,0 +1,33 @@
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 before_die {
my ($self, %args) = @_;
print "PLUGIN before_die\n";
print "Exit status: $args{exit_status}\n";
}
sub after_create_new_table {
my ($self, %args) = @_;
print "PLUGIN after_create_new_table\n";
my $dbh = $self->{aux_cxn}->dbh;
my $new_tbl = $args{new_tbl}->{name};
# Remove PRIMARY KEY, so pt-osc fails with an error and handles
# it in the _die call
$dbh->do("ALTER TABLE ${new_tbl} MODIFY COLUMN id INT NOT NULL, DROP PRIMARY KEY");
}
1;

View File

@@ -0,0 +1,32 @@
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 before_die {
my ($self, %args) = @_;
print "PLUGIN before_die\n";
print "Exit status: $args{exit_status}\n";
}
sub on_copy_rows_after_nibble {
my ($self, %args) = @_;
my $tbl = $args{tbl};
print "PLUGIN on_copy_rows_after_nibble\n";
if ($tbl->{row_cnt} > 1000) {
my $dbh = $self->{aux_cxn}->dbh;
# Run invalid query to get error
$dbh->do("SELECT * FRO " . $tbl->{name});
}
}
1;

View File

@@ -0,0 +1,32 @@
Thread 69 (Thread 0x7fd4b0049640 (LWP 15380)):
#0 0x00007fd4b5c36dc0 in __lll_lock_wait () from /lib64/libpthread.so.0
#1 0x00007fd4b5c31703 in __pthread_mutex_cond_lock () from /lib64/libpthread.so.0
#2 0x0000000001fa7130 in os_event::wait (this=0x7fd4ac8afbe8) at /home/zongzhi.czz/git/mysql-8.0/storage/innobase/os/os0event.cc:189
#3 os_event::wait_low (this=0x7fd4ac8afbe8, reset_sig_count=3187477) at /home/zongzhi.czz/git/mysql-8.0/storage/innobase/os/os0event.cc:372
#4 0x0000000001fa743a in os_event_wait_low (event=<optimized out>, reset_sig_count=<optimized out>) at /home/zongzhi.czz/git/mysql-8.0/storage/innobase/os/os0event.cc:608
#5 0x000000000206e390 in sync_array_wait_event (arr=arr@entry=0x7fd4ac009ab8, cell=@0x7fd4b0044658: 0x7fd4b23b8028) at /home/zongzhi.czz/git/mysql-8.0/storage/innobase/sync/sync0arr.cc:444
#6 0x0000000002071b5a in rw_lock_sx_lock_func (lock=0x7fd4ac85b2d8, pass=pass@entry=0, file_name=file_name@entry=0x2cfe1f0 "/home/zongzhi.czz/git/mysql-8.0/storage/innobase/btr/btr0cur.cc", line=line@entry=836) at /home/zongzhi.czz/git/mysql-8.0/storage/innobase/sync/sync0rw.cc:829
#7 0x00000000020f2ae5 in pfs_rw_lock_sx_lock_func (lock=lock@entry=0x7fd4ac85b2d8, file_name=file_name@entry=0x2cfe1f0 "/home/zongzhi.czz/git/mysql-8.0/storage/innobase/btr/btr0cur.cc", line=line@entry=836, pass=0) at /home/zongzhi.czz/git/mysql-8.0/storage/innobase/include/sync0rw.ic:736
#8 0x00000000020fe967 in mtr_t::sx_lock (line=836, file=0x2cfe1f0 "/home/zongzhi.czz/git/mysql-8.0/storage/innobase/btr/btr0cur.cc", lock=<optimized out>, this=0x7fd4b0045de0) at /home/zongzhi.czz/git/mysql-8.0/storage/innobase/include/mtr0mtr.ic:242
#9 btr_cur_search_to_nth_level (index=index@entry=0x7fd4ac85b188, level=level@entry=0, tuple=tuple@entry=0x7f8e4401ddd8, mode=mode@entry=PAGE_CUR_LE, latch_mode=latch_mode@entry=33, cursor=cursor@entry=0x7fd4b00456a0, has_search_latch=0, file=0x2cf3498 "/home/zongzhi.czz/git/mysql-8.0/storage/innobase/row/row0ins.cc", line=2404, mtr=0x7fd4b0045de0) at /home/zongzhi.czz/git/mysql-8.0/storage/innobase/btr/btr0cur.cc:836
#10 0x0000000001fec091 in btr_pcur_t::open (line=2404, file=0x2cf3498 "/home/zongzhi.czz/git/mysql-8.0/storage/innobase/row/row0ins.cc", mtr=0x7fd4b0045de0, latch_mode=33, mode=PAGE_CUR_LE, tuple=0x7f8e4401ddd8, level=0, index=0x7fd4ac85b188, this=0x7fd4b00456a0) at /home/zongzhi.czz/git/mysql-8.0/storage/innobase/include/btr0pcur.h:631#11 row_ins_clust_index_entry_low (flags=<optimized out>, mode=mode@entry=33, index=index@entry=0x7fd4ac85b188, n_uniq=n_uniq@entry=1, entry=entry@entry=0x7f8e4401ddd8, n_ext=n_ext@entry=0, thr=<optimized out>, dup_chk_only=<optimized out>) at /home/zongzhi.czz/git/mysql-8.0/storage/innobase/row/row0ins.cc:2404
#12 0x0000000001ff2493 in row_ins_clust_index_entry (index=0x7fd4ac85b188, entry=entry@entry=0x7f8e4401ddd8, thr=thr@entry=0x7f8e4401d358, n_ext=n_ext@entry=0, dup_chk_only=dup_chk_only@entry=false) at /home/zongzhi.czz/git/mysql-8.0/storage/innobase/row/row0ins.cc:3128
#13 0x0000000001ff351f in row_ins_index_entry (thr=0x7f8e4401d358, multi_val_pos=@0x7f8e4401d0d0: 0, entry=0x7f8e4401ddd8, index=<optimized out>) at /home/zongzhi.czz/git/mysql-8.0/storage/innobase/row/row0ins.cc:3295
#14 row_ins_index_entry_step (thr=0x7f8e4401d358, node=0x7f8e4401d018) at /home/zongzhi.czz/git/mysql-8.0/storage/innobase/row/row0ins.cc:3432
#15 row_ins (thr=0x7f8e4401d358, node=0x7f8e4401d018) at /home/zongzhi.czz/git/mysql-8.0/storage/innobase/row/row0ins.cc:3551
#16 row_ins_step (thr=thr@entry=0x7f8e4401d358) at /home/zongzhi.czz/git/mysql-8.0/storage/innobase/row/row0ins.cc:3675
#17 0x0000000002004cac in row_insert_for_mysql_using_ins_graph (mysql_rec=mysql_rec@entry=0x7f8e4400ae58 "\377\064y\002\a\005\250X272262038040-36454966916-40203159830-44114922317-57338906833-90459983776-67841547117-58042251992-67222347817-09932413691 62585243489-83708933349-63627342446-67953416665-46385069319 ", prebuilt=<optimized out>) at /home/zongzhi.czz/git/mysql-8.0/storage/innobase/row/row0mysql.cc:1580
#18 0x0000000002007534 in row_insert_for_mysql (mysql_rec=mysql_rec@entry=0x7f8e4400ae58 "\377\064y\002\a\005\250X272262038040-36454966916-40203159830-44114922317-57338906833-90459983776-67841547117-58042251992-67222347817-09932413691 62585243489-83708933349-63627342446-67953416665-46385069319 ", prebuilt=<optimized out>) at /home/zongzhi.czz/git/mysql-8.0/storage/innobase/row/row0mysql.cc:1706
#19 0x0000000001ee9b99 in ha_innobase::write_row (this=0x7f8e4401b138, record=0x7f8e4400ae58 "\377\064y\002\a\005\250X272262038040-36454966916-40203159830-44114922317-57338906833-90459983776-67841547117-58042251992-67222347817-09932413691 62585243489-83708933349-63627342446-67953416665-46385069319 ") at /home/zongzhi.czz/git/mysql-8.0/storage/innobase/handler/ha_innodb.cc:8581
#20 0x0000000001018054 in handler::ha_write_row (this=0x7f8e4401b138, buf=0x7f8e4400ae58 "\377\064y\002\a\005\250X272262038040-36454966916-40203159830-44114922317-57338906833-90459983776-67841547117-58042251992-67222347817-09932413691 62585243489-83708933349-63627342446-67953416665-46385069319 ") at /home/zongzhi.czz/git/mysql-8.0/sql/handler.cc:7740
#21 0x0000000001208d25 in write_record (thd=thd@entry=0x7f8e44000f10, table=table@entry=0x7f8e4400a4b0, info=info@entry=0x7fd4b0046a10, update=update@entry=0x7fd4b0046a90) at /home/zongzhi.czz/git/mysql-8.0/sql/sql_insert.cc:1946
#22 0x0000000001209e81 in Sql_cmd_insert_values::execute_inner (this=0x7f8e4400e2b0, thd=0x7f8e44000f10) at /home/zongzhi.czz/git/mysql-8.0/sql/sql_insert.cc:614
#23 0x0000000000e22e78 in Sql_cmd_dml::execute (this=0x7f8e4400e2b0, thd=0x7f8e44000f10) at /home/zongzhi.czz/git/mysql-8.0/sql/sql_select.cc:704
#24 0x0000000000dd5da9 in mysql_execute_command (thd=thd@entry=0x7f8e44000f10, first_level=first_level@entry=true) at /home/zongzhi.czz/git/mysql-8.0/sql/sql_parse.cc:3450
#25 0x0000000000dd80c1 in mysql_parse (thd=thd@entry=0x7f8e44000f10, parser_state=parser_state@entry=0x7fd4b0048450) at /home/zongzhi.czz/git/mysql-8.0/sql/sql_parse.cc:5257
#26 0x0000000000dda8ad in dispatch_command (thd=thd@entry=0x7f8e44000f10, com_data=com_data@entry=0x7fd4b0048b40, command=COM_QUERY) at /home/zongzhi.czz/git/mysql-8.0/sql/sql_parse.cc:1765
#27 0x0000000000ddb34c in do_command (thd=thd@entry=0x7f8e44000f10) at /home/zongzhi.czz/git/mysql-8.0/sql/sql_parse.cc:1273
#28 0x0000000000eea308 in handle_connection (arg=arg@entry=0x3e8c480) at /home/zongzhi.czz/git/mysql-8.0/sql/conn_handler/connection_handler_per_thread.cc:302
#29 0x0000000002303059 in pfs_spawn_thread (arg=0x3f025d0) at /home/zongzhi.czz/git/mysql-8.0/storage/perfschema/pfs.cc:2854
#30 0x00007fd4b5c2d3f9 in start_thread () from /lib64/libpthread.so.0
#31 0x00007fd4b4ca4303 in clone () from /lib64/libc.so.6

View File

@@ -0,0 +1 @@
1 __lll_lock_wait(libpthread.so.0),__pthread_mutex_cond_lock(libpthread.so.0),os_event::wait(os0event.cc:189),os_event::wait_low(os0event.cc:372),os_event_wait_low(os0event.cc:608),sync_array_wait_event(sync0arr.cc:444),rw_lock_sx_lock_func(sync0rw.cc:829),pfs_rw_lock_sx_lock_func(sync0rw.ic:736),mtr_t::sx_lock(mtr0mtr.ic:242),btr_cur_search_to_nth_level(btr0cur.cc:836),btr_pcur_t::open(row0ins.cc:2404),row_ins_clust_index_entry(row0ins.cc:3128),row_ins_index_entry(row0ins.cc:3295),row_ins_index_entry_step(row0ins.cc:3432),row_ins(row0ins.cc:3551),row_ins_step(row0ins.cc:3675),row_insert_for_mysql_using_ins_graph(row0mysql.cc:1580),row_insert_for_mysql(row0mysql.cc:1706),ha_innobase::write_row(ha_innodb.cc:8581),handler::ha_write_row(handler.cc:7740),write_record(sql_insert.cc:1946),Sql_cmd_insert_values::execute_inner(sql_insert.cc:614),Sql_cmd_dml::execute(sql_select.cc:704),mysql_execute_command(sql_parse.cc:3450),mysql_parse(sql_parse.cc:5257),dispatch_command(sql_parse.cc:1765),do_command(sql_parse.cc:1273),handle_connection(connection_handler_per_thread.cc:302),pfs_spawn_thread(pfs.cc:2854),start_thread(libpthread.so.0),clone(libc.so.6)

View File

@@ -5,5 +5,5 @@
3 pthread_cond_wait,MYSQL_LOG::wait_for_update
1 select(libc.so.6),handle_connections_sockets
1 do_sigwait(libpthread.so.0),sigwait(libpthread.so.0)
1 btr_search_guess_on_hash(libc.so.6),btr_cur_search_to_nth_level
1 btr_search_guess_on_hash,btr_cur_search_to_nth_level
1 btr_cur_search_to_nth_level,btr_estimate_n_rows_in_range

View File

@@ -1,5 +1,5 @@
35 pthread_cond_wait,end_thread,handle_one_connection,start_thread(libpthread.so.0),clone(libc.so.6)
20 read(libpthread.so.0),read(unistd.h:35),vio_read(unistd.h:35),my_real_read,my_net_read,handle_one_connection,start_thread(libpthread.so.0),clone(libc.so.6)
20 read(libpthread.so.0),read(unistd.h:35),vio_read,my_real_read,my_net_read,handle_one_connection,start_thread(libpthread.so.0),clone(libc.so.6)
18 pthread_cond_wait,os_event_wait_low,os_aio_simulated_handle,fil_aio_wait,io_handler_thread,start_thread(libpthread.so.0),clone(libc.so.6)
3 pthread_cond_wait,MYSQL_LOG::wait_for_update,mysql_binlog_send,dispatch_command,handle_one_connection,start_thread(libpthread.so.0),clone(libc.so.6)
1 select(libc.so.6),os_thread_sleep,srv_master_thread,start_thread(libpthread.so.0),clone(libc.so.6)
@@ -7,5 +7,5 @@
1 select(libc.so.6),os_thread_sleep,srv_error_monitor_thread,start_thread(libpthread.so.0),clone(libc.so.6)
1 select(libc.so.6),handle_connections_sockets,main
1 do_sigwait(libpthread.so.0),sigwait(libpthread.so.0),signal_hand,start_thread(libpthread.so.0),clone(libc.so.6)
1 btr_search_guess_on_hash(libc.so.6),btr_cur_search_to_nth_level,btr_pcur_open_with_no_init,row_search_for_mysql,ha_innobase::index_read,join_read_always_key,sub_select,evaluate_join_record,sub_select,evaluate_join_record,sub_select,evaluate_join_record,sub_select,evaluate_join_record,sub_select,evaluate_join_record,sub_select,do_select,JOIN::exec,mysql_select,handle_select,mysql_execute_command,mysql_parse,dispatch_command,handle_one_connection,start_thread(libpthread.so.0),clone(libc.so.6)
1 btr_search_guess_on_hash,btr_cur_search_to_nth_level,btr_pcur_open_with_no_init,row_search_for_mysql,ha_innobase::index_read,join_read_always_key,sub_select,evaluate_join_record,sub_select,evaluate_join_record,sub_select,evaluate_join_record,sub_select,evaluate_join_record,sub_select,evaluate_join_record,sub_select,do_select,JOIN::exec,mysql_select,handle_select,mysql_execute_command,mysql_parse,dispatch_command,handle_one_connection,start_thread(libpthread.so.0),clone(libc.so.6)
1 btr_cur_search_to_nth_level,btr_estimate_n_rows_in_range,ha_innobase::records_in_range,check_quick_keys,check_quick_keys,check_quick_keys,check_quick_keys,check_quick_keys,check_quick_keys,check_quick_keys,check_quick_keys,check_quick_keys,check_quick_keys,check_quick_keys,check_quick_select,get_key_scans_params,SQL_SELECT::test_quick_select,get_quick_record_count,make_join_statistics,JOIN::optimize,mysql_select,handle_select,mysql_execute_command,mysql_parse,dispatch_command,handle_one_connection,start_thread(libpthread.so.0),clone(libc.so.6)

View File

@@ -45,6 +45,27 @@ ok(
),
'Analysis for slow007 with --explain, no rows',
);
# output=json
SKIP: {
skip "output=json tests require 5.7" unless $sandbox_version ge '5.7';
my $jq = `which jq`;
chomp $jq;
skip "output=json tests require jq" unless -x "$jq";
ok(
no_diff(
sub { pt_query_digest::main(@args, '--output=json',
"$trunk/t/lib/samples/slowlogs/slow007.txt") },
( $sandbox_version ge '8.0' ? "t/pt-query-digest/samples/slow007_explain_json_1-80.txt"
: "t/pt-query-digest/samples/slow007_explain_json_1-57.txt"),
post_pipe => 'jq -S .',
),
'Analysis for slow007 with --explain and --output=json, no rows',
);
}
# Normalish output from EXPLAIN.
$dbh->do("insert into trees values ('apple'),('orange'),('banana')");
@@ -60,6 +81,26 @@ ok(
'Analysis for slow007 with --explain',
);
# output=json
SKIP: {
skip "output=json tests require 5.7" unless $sandbox_version ge '5.7';
my $jq = `which jq`;
chomp $jq;
skip "output=json tests require jq" unless -x "$jq";
ok(
no_diff(
sub { pt_query_digest::main(@args, '--output=json',
"$trunk/t/lib/samples/slowlogs/slow007.txt") },
( $sandbox_version ge '8.0' ? "t/pt-query-digest/samples/slow007_explain_json_2-80.txt"
: "t/pt-query-digest/samples/slow007_explain_json_2-57.txt"),
post_pipe => 'jq -S .',
),
'Analysis for slow007 with --explain and --output=json',
);
}
# #############################################################################
# Issue 1141: Add "spark charts" to mk-query-digest profile
# #############################################################################

View File

@@ -0,0 +1,216 @@
{
"classes": [
{
"attribute": "fingerprint",
"checksum": "88F3D65BE48113F18E306CDB7A800841",
"distillate": "SELECT trees",
"example": {
"Query_time": "0.000012",
"explain": "# *************************** 1. row ***************************\n# id: 1\n# select_type: SIMPLE\n# table: trees\n# partitions: NULL\n# type: index\n# possible_keys: NULL\n# key: fruit\n# key_len: 27\n# ref: NULL\n# rows: 1\n# filtered: 100.00\n# Extra: Using index\n",
"query": "SELECT fruit FROM trees",
"ts": "2007-12-18 11:48:27"
},
"fingerprint": "select fruit from trees",
"histograms": {
"Query_time": [
0,
1,
0,
0,
0,
0,
0,
0
]
},
"metrics": {
"Filesort": {
"yes": "0"
},
"Filesort_on_disk": {
"yes": "0"
},
"Full_join": {
"yes": "0"
},
"Full_scan": {
"yes": "0"
},
"Lock_time": {
"avg": "0.000000",
"max": "0.000000",
"median": "0.000000",
"min": "0.000000",
"pct": "1.000000",
"pct_95": "0.000000",
"stddev": "0.000000",
"sum": "0.000000"
},
"Merge_passes": {
"avg": "0",
"max": "0",
"median": "0",
"min": "0",
"pct": "1",
"pct_95": "0",
"stddev": "0",
"sum": "0"
},
"QC_Hit": {
"yes": "0"
},
"Query_length": {
"avg": "23",
"max": "23",
"median": "23",
"min": "23",
"pct": "1",
"pct_95": "23",
"stddev": "0",
"sum": "23"
},
"Query_time": {
"avg": "0.000012",
"max": "0.000012",
"median": "0.000012",
"min": "0.000012",
"pct": "1.000000",
"pct_95": "0.000012",
"stddev": "0.000000",
"sum": "0.000012"
},
"Rows_examined": {
"avg": "0",
"max": "0",
"median": "0",
"min": "0",
"pct": "1",
"pct_95": "0",
"stddev": "0",
"sum": "0"
},
"Rows_sent": {
"avg": "0",
"max": "0",
"median": "0",
"min": "0",
"pct": "1",
"pct_95": "0",
"stddev": "0",
"sum": "0"
},
"Tmp_table": {
"yes": "0"
},
"Tmp_table_on_disk": {
"yes": "0"
},
"db": {
"value": "food"
},
"host": {
"value": ""
},
"user": {
"value": "[SQL_SLAVE]"
}
},
"query_count": 1,
"tables": [
{
"create": "SHOW CREATE TABLE `food`.`trees`\\G",
"status": "SHOW TABLE STATUS FROM `food` LIKE 'trees'\\G"
}
],
"ts_max": "2007-12-18 11:48:27",
"ts_min": "2007-12-18 11:48:27"
}
],
"global": {
"files": [
{
"name": "/home/sveta/src/percona/percona-toolkit/t/lib/samples/slowlogs/slow007.txt",
"size": 368
}
],
"metrics": {
"Filesort": {
"cnt": "0"
},
"Filesort_on_disk": {
"cnt": "0"
},
"Full_join": {
"cnt": "0"
},
"Full_scan": {
"cnt": "0"
},
"Lock_time": {
"avg": "0.000000",
"max": "0.000000",
"median": "0.000000",
"min": "0.000000",
"pct_95": "0.000000",
"stddev": "0.000000",
"sum": "0.000000"
},
"Merge_passes": {
"avg": "0",
"max": "0",
"median": "0",
"min": "0",
"pct_95": "0",
"stddev": "0",
"sum": "0"
},
"QC_Hit": {
"cnt": "0"
},
"Query_length": {
"avg": "23",
"max": "23",
"median": "23",
"min": "23",
"pct_95": "23",
"stddev": "0",
"sum": "23"
},
"Query_time": {
"avg": "0.000012",
"max": "0.000012",
"median": "0.000012",
"min": "0.000012",
"pct_95": "0.000012",
"stddev": "0.000000",
"sum": "0.000012"
},
"Rows_examined": {
"avg": "0",
"max": "0",
"median": "0",
"min": "0",
"pct_95": "0",
"stddev": "0",
"sum": "0"
},
"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": 1,
"unique_query_count": 1
}
}

View File

@@ -0,0 +1,216 @@
{
"classes": [
{
"attribute": "fingerprint",
"checksum": "88F3D65BE48113F18E306CDB7A800841",
"distillate": "SELECT trees",
"example": {
"Query_time": "0.000012",
"explain": "# *************************** 1. row ***************************\n# id: 1\n# select_type: SIMPLE\n# table: trees\n# partitions: NULL\n# type: index\n# possible_keys: NULL\n# key: fruit\n# key_len: 99\n# ref: NULL\n# rows: 1\n# filtered: 100.00\n# Extra: Using index\n",
"query": "SELECT fruit FROM trees",
"ts": "2007-12-18 11:48:27"
},
"fingerprint": "select fruit from trees",
"histograms": {
"Query_time": [
0,
1,
0,
0,
0,
0,
0,
0
]
},
"metrics": {
"Filesort": {
"yes": "0"
},
"Filesort_on_disk": {
"yes": "0"
},
"Full_join": {
"yes": "0"
},
"Full_scan": {
"yes": "0"
},
"Lock_time": {
"avg": "0.000000",
"max": "0.000000",
"median": "0.000000",
"min": "0.000000",
"pct": "1.000000",
"pct_95": "0.000000",
"stddev": "0.000000",
"sum": "0.000000"
},
"Merge_passes": {
"avg": "0",
"max": "0",
"median": "0",
"min": "0",
"pct": "1",
"pct_95": "0",
"stddev": "0",
"sum": "0"
},
"QC_Hit": {
"yes": "0"
},
"Query_length": {
"avg": "23",
"max": "23",
"median": "23",
"min": "23",
"pct": "1",
"pct_95": "23",
"stddev": "0",
"sum": "23"
},
"Query_time": {
"avg": "0.000012",
"max": "0.000012",
"median": "0.000012",
"min": "0.000012",
"pct": "1.000000",
"pct_95": "0.000012",
"stddev": "0.000000",
"sum": "0.000012"
},
"Rows_examined": {
"avg": "0",
"max": "0",
"median": "0",
"min": "0",
"pct": "1",
"pct_95": "0",
"stddev": "0",
"sum": "0"
},
"Rows_sent": {
"avg": "0",
"max": "0",
"median": "0",
"min": "0",
"pct": "1",
"pct_95": "0",
"stddev": "0",
"sum": "0"
},
"Tmp_table": {
"yes": "0"
},
"Tmp_table_on_disk": {
"yes": "0"
},
"db": {
"value": "food"
},
"host": {
"value": ""
},
"user": {
"value": "[SQL_SLAVE]"
}
},
"query_count": 1,
"tables": [
{
"create": "SHOW CREATE TABLE `food`.`trees`\\G",
"status": "SHOW TABLE STATUS FROM `food` LIKE 'trees'\\G"
}
],
"ts_max": "2007-12-18 11:48:27",
"ts_min": "2007-12-18 11:48:27"
}
],
"global": {
"files": [
{
"name": "/home/sveta/src/percona/percona-toolkit/t/lib/samples/slowlogs/slow007.txt",
"size": 368
}
],
"metrics": {
"Filesort": {
"cnt": "0"
},
"Filesort_on_disk": {
"cnt": "0"
},
"Full_join": {
"cnt": "0"
},
"Full_scan": {
"cnt": "0"
},
"Lock_time": {
"avg": "0.000000",
"max": "0.000000",
"median": "0.000000",
"min": "0.000000",
"pct_95": "0.000000",
"stddev": "0.000000",
"sum": "0.000000"
},
"Merge_passes": {
"avg": "0",
"max": "0",
"median": "0",
"min": "0",
"pct_95": "0",
"stddev": "0",
"sum": "0"
},
"QC_Hit": {
"cnt": "0"
},
"Query_length": {
"avg": "23",
"max": "23",
"median": "23",
"min": "23",
"pct_95": "23",
"stddev": "0",
"sum": "23"
},
"Query_time": {
"avg": "0.000012",
"max": "0.000012",
"median": "0.000012",
"min": "0.000012",
"pct_95": "0.000012",
"stddev": "0.000000",
"sum": "0.000012"
},
"Rows_examined": {
"avg": "0",
"max": "0",
"median": "0",
"min": "0",
"pct_95": "0",
"stddev": "0",
"sum": "0"
},
"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": 1,
"unique_query_count": 1
}
}

View File

@@ -0,0 +1,216 @@
{
"classes": [
{
"attribute": "fingerprint",
"checksum": "88F3D65BE48113F18E306CDB7A800841",
"distillate": "SELECT trees",
"example": {
"Query_time": "0.000012",
"explain": "# *************************** 1. row ***************************\n# id: 1\n# select_type: SIMPLE\n# table: trees\n# partitions: NULL\n# type: index\n# possible_keys: NULL\n# key: fruit\n# key_len: 27\n# ref: NULL\n# rows: 3\n# filtered: 100.00\n# Extra: Using index\n",
"query": "SELECT fruit FROM trees",
"ts": "2007-12-18 11:48:27"
},
"fingerprint": "select fruit from trees",
"histograms": {
"Query_time": [
0,
1,
0,
0,
0,
0,
0,
0
]
},
"metrics": {
"Filesort": {
"yes": "0"
},
"Filesort_on_disk": {
"yes": "0"
},
"Full_join": {
"yes": "0"
},
"Full_scan": {
"yes": "0"
},
"Lock_time": {
"avg": "0.000000",
"max": "0.000000",
"median": "0.000000",
"min": "0.000000",
"pct": "1.000000",
"pct_95": "0.000000",
"stddev": "0.000000",
"sum": "0.000000"
},
"Merge_passes": {
"avg": "0",
"max": "0",
"median": "0",
"min": "0",
"pct": "1",
"pct_95": "0",
"stddev": "0",
"sum": "0"
},
"QC_Hit": {
"yes": "0"
},
"Query_length": {
"avg": "23",
"max": "23",
"median": "23",
"min": "23",
"pct": "1",
"pct_95": "23",
"stddev": "0",
"sum": "23"
},
"Query_time": {
"avg": "0.000012",
"max": "0.000012",
"median": "0.000012",
"min": "0.000012",
"pct": "1.000000",
"pct_95": "0.000012",
"stddev": "0.000000",
"sum": "0.000012"
},
"Rows_examined": {
"avg": "0",
"max": "0",
"median": "0",
"min": "0",
"pct": "1",
"pct_95": "0",
"stddev": "0",
"sum": "0"
},
"Rows_sent": {
"avg": "0",
"max": "0",
"median": "0",
"min": "0",
"pct": "1",
"pct_95": "0",
"stddev": "0",
"sum": "0"
},
"Tmp_table": {
"yes": "0"
},
"Tmp_table_on_disk": {
"yes": "0"
},
"db": {
"value": "food"
},
"host": {
"value": ""
},
"user": {
"value": "[SQL_SLAVE]"
}
},
"query_count": 1,
"tables": [
{
"create": "SHOW CREATE TABLE `food`.`trees`\\G",
"status": "SHOW TABLE STATUS FROM `food` LIKE 'trees'\\G"
}
],
"ts_max": "2007-12-18 11:48:27",
"ts_min": "2007-12-18 11:48:27"
}
],
"global": {
"files": [
{
"name": "/home/sveta/src/percona/percona-toolkit/t/lib/samples/slowlogs/slow007.txt",
"size": 368
}
],
"metrics": {
"Filesort": {
"cnt": "0"
},
"Filesort_on_disk": {
"cnt": "0"
},
"Full_join": {
"cnt": "0"
},
"Full_scan": {
"cnt": "0"
},
"Lock_time": {
"avg": "0.000000",
"max": "0.000000",
"median": "0.000000",
"min": "0.000000",
"pct_95": "0.000000",
"stddev": "0.000000",
"sum": "0.000000"
},
"Merge_passes": {
"avg": "0",
"max": "0",
"median": "0",
"min": "0",
"pct_95": "0",
"stddev": "0",
"sum": "0"
},
"QC_Hit": {
"cnt": "0"
},
"Query_length": {
"avg": "23",
"max": "23",
"median": "23",
"min": "23",
"pct_95": "23",
"stddev": "0",
"sum": "23"
},
"Query_time": {
"avg": "0.000012",
"max": "0.000012",
"median": "0.000012",
"min": "0.000012",
"pct_95": "0.000012",
"stddev": "0.000000",
"sum": "0.000012"
},
"Rows_examined": {
"avg": "0",
"max": "0",
"median": "0",
"min": "0",
"pct_95": "0",
"stddev": "0",
"sum": "0"
},
"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": 1,
"unique_query_count": 1
}
}

View File

@@ -0,0 +1,216 @@
{
"classes": [
{
"attribute": "fingerprint",
"checksum": "88F3D65BE48113F18E306CDB7A800841",
"distillate": "SELECT trees",
"example": {
"Query_time": "0.000012",
"explain": "# *************************** 1. row ***************************\n# id: 1\n# select_type: SIMPLE\n# table: trees\n# partitions: NULL\n# type: index\n# possible_keys: NULL\n# key: fruit\n# key_len: 99\n# ref: NULL\n# rows: 3\n# filtered: 100.00\n# Extra: Using index\n",
"query": "SELECT fruit FROM trees",
"ts": "2007-12-18 11:48:27"
},
"fingerprint": "select fruit from trees",
"histograms": {
"Query_time": [
0,
1,
0,
0,
0,
0,
0,
0
]
},
"metrics": {
"Filesort": {
"yes": "0"
},
"Filesort_on_disk": {
"yes": "0"
},
"Full_join": {
"yes": "0"
},
"Full_scan": {
"yes": "0"
},
"Lock_time": {
"avg": "0.000000",
"max": "0.000000",
"median": "0.000000",
"min": "0.000000",
"pct": "1.000000",
"pct_95": "0.000000",
"stddev": "0.000000",
"sum": "0.000000"
},
"Merge_passes": {
"avg": "0",
"max": "0",
"median": "0",
"min": "0",
"pct": "1",
"pct_95": "0",
"stddev": "0",
"sum": "0"
},
"QC_Hit": {
"yes": "0"
},
"Query_length": {
"avg": "23",
"max": "23",
"median": "23",
"min": "23",
"pct": "1",
"pct_95": "23",
"stddev": "0",
"sum": "23"
},
"Query_time": {
"avg": "0.000012",
"max": "0.000012",
"median": "0.000012",
"min": "0.000012",
"pct": "1.000000",
"pct_95": "0.000012",
"stddev": "0.000000",
"sum": "0.000012"
},
"Rows_examined": {
"avg": "0",
"max": "0",
"median": "0",
"min": "0",
"pct": "1",
"pct_95": "0",
"stddev": "0",
"sum": "0"
},
"Rows_sent": {
"avg": "0",
"max": "0",
"median": "0",
"min": "0",
"pct": "1",
"pct_95": "0",
"stddev": "0",
"sum": "0"
},
"Tmp_table": {
"yes": "0"
},
"Tmp_table_on_disk": {
"yes": "0"
},
"db": {
"value": "food"
},
"host": {
"value": ""
},
"user": {
"value": "[SQL_SLAVE]"
}
},
"query_count": 1,
"tables": [
{
"create": "SHOW CREATE TABLE `food`.`trees`\\G",
"status": "SHOW TABLE STATUS FROM `food` LIKE 'trees'\\G"
}
],
"ts_max": "2007-12-18 11:48:27",
"ts_min": "2007-12-18 11:48:27"
}
],
"global": {
"files": [
{
"name": "/home/sveta/src/percona/percona-toolkit/t/lib/samples/slowlogs/slow007.txt",
"size": 368
}
],
"metrics": {
"Filesort": {
"cnt": "0"
},
"Filesort_on_disk": {
"cnt": "0"
},
"Full_join": {
"cnt": "0"
},
"Full_scan": {
"cnt": "0"
},
"Lock_time": {
"avg": "0.000000",
"max": "0.000000",
"median": "0.000000",
"min": "0.000000",
"pct_95": "0.000000",
"stddev": "0.000000",
"sum": "0.000000"
},
"Merge_passes": {
"avg": "0",
"max": "0",
"median": "0",
"min": "0",
"pct_95": "0",
"stddev": "0",
"sum": "0"
},
"QC_Hit": {
"cnt": "0"
},
"Query_length": {
"avg": "23",
"max": "23",
"median": "23",
"min": "23",
"pct_95": "23",
"stddev": "0",
"sum": "23"
},
"Query_time": {
"avg": "0.000012",
"max": "0.000012",
"median": "0.000012",
"min": "0.000012",
"pct_95": "0.000012",
"stddev": "0.000000",
"sum": "0.000012"
},
"Rows_examined": {
"avg": "0",
"max": "0",
"median": "0",
"min": "0",
"pct_95": "0",
"stddev": "0",
"sum": "0"
},
"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": 1,
"unique_query_count": 1
}
}

View File

@@ -221,6 +221,21 @@ like(
qr/$skipping_str/s,
"--skip-check-slave-lag",
);
# Test for skip-check-slave-lag and empty replica port
$output = output(
sub { pt_table_checksum::main(@args,
'--skip-check-slave-lag', "h=127.0.0.1",
),
},
stderr => 1
);
unlike(
$output,
qr/Use of uninitialized value.*/,
'No syntax error if port is missed in --skip-check-slave-lag DSN',
) or diag($output);
}
# #############################################################################
# Illegal division by zero at pt-table-checksum line 7950