mirror of
https://github.com/percona/percona-toolkit.git
synced 2026-02-27 02:00:57 +08:00
PT-1717 - resume pt-online-schema-change if it's interrupted
- Insert row with Job ID into the history table - Update job row with progress, set 'done' to 'yes' when finished succesfully
This commit is contained in:
@@ -8796,19 +8796,31 @@ sub main {
|
||||
my $cxn = $make_cxn->(dsn => $dsn);
|
||||
my $aux_cxn = $make_cxn->(dsn => $dsn, prev_dsn => $dsn);
|
||||
|
||||
my $hist_table = $q->quote($q->split_unquote($o->get('history-table')));
|
||||
my $job_id;
|
||||
my $hist_sth;
|
||||
my $done_sth;
|
||||
|
||||
if ( $o->get('history') ) {
|
||||
my $got_json = eval { require JSON };
|
||||
if ( $EVAL_ERROR ) {
|
||||
die("Option --history requires Perl JSON module.\n"
|
||||
. "Install via cpanm:\n\tcpanm JSON\n"
|
||||
. "Install via CPAN shell::\n\tperl -MCPAN -e shell\n\tinstall JSON\n"
|
||||
. "Install on Debian/Ubuntu:\n\tapt install -y libjson-perl\n"
|
||||
. "Install on RedHat/OEL/CentOS:\n\tyum -y install perl-JSON\n"
|
||||
);
|
||||
}
|
||||
create_history_table(
|
||||
dbh => $cxn->dbh(),
|
||||
hist_table => $o->get('history-table'),
|
||||
dbh => $cxn->dbh(),
|
||||
hist_table => $hist_table,
|
||||
OptionParser => $o,
|
||||
TableParser => $tp,
|
||||
Quoter => $q,
|
||||
);
|
||||
# parsing args here
|
||||
use JSON;
|
||||
my $json = JSON->new->allow_nonref;
|
||||
my %opts = $o->opts();
|
||||
_d("DB: $db, tbl: $tbl");
|
||||
my $opt_hash = {};
|
||||
while ( my ($opt, $value) = each (%opts) ) {
|
||||
if ( $value->{got} ) {
|
||||
@@ -8816,10 +8828,22 @@ sub main {
|
||||
}
|
||||
}
|
||||
my $json_str = $json->encode($opt_hash);
|
||||
print "$json_str\n";
|
||||
|
||||
#_d(Dumper($o->opts()));
|
||||
|
||||
|
||||
my $insert_sth = $cxn->dbh()->prepare(
|
||||
"INSERT INTO ${hist_table} (db, tbl, altr, args)"
|
||||
. "VALUES(?, ?, ?, ?)"
|
||||
);
|
||||
PTDEBUG && _d($insert_sth);
|
||||
$insert_sth->execute($db, $tbl, $o->get('alter'), $json_str);
|
||||
$job_id = $insert_sth->last_insert_id();
|
||||
$hist_sth = $cxn->dbh()->prepare(
|
||||
"UPDATE ${hist_table} SET lower_boundary = ?, upper_boundary = ? "
|
||||
. "WHERE job_id = ${job_id}"
|
||||
);
|
||||
$done_sth = $cxn->dbh()->prepare(
|
||||
"UPDATE ${hist_table} SET done = 'yes' "
|
||||
. "WHERE job_id = ${job_id}"
|
||||
);
|
||||
}
|
||||
|
||||
my $cluster = Percona::XtraDB::Cluster->new;
|
||||
@@ -10066,10 +10090,11 @@ sub main {
|
||||
# Exec and time the chunk checksum query.
|
||||
$tbl->{nibble_time} = exec_nibble(
|
||||
%args,
|
||||
tries => $tries,
|
||||
Retry => $retry,
|
||||
Quoter => $q,
|
||||
stats => \%stats,
|
||||
tries => $tries,
|
||||
Retry => $retry,
|
||||
Quoter => $q,
|
||||
stats => \%stats,
|
||||
hist_sth => $hist_sth,
|
||||
);
|
||||
PTDEBUG && _d('Nibble time:', $tbl->{nibble_time});
|
||||
|
||||
@@ -10174,6 +10199,9 @@ sub main {
|
||||
},
|
||||
done => sub {
|
||||
if ( $o->get('execute') ) {
|
||||
if ( $o->get('history') ) {
|
||||
$done_sth->execute();
|
||||
}
|
||||
print ts("Copied rows OK.\n");
|
||||
}
|
||||
},
|
||||
@@ -12014,6 +12042,7 @@ sub exec_nibble {
|
||||
my $ub_quoted = $q->serialize_list(@{$boundary->{upper}});
|
||||
my $chunk = $nibble_iter->nibble_number();
|
||||
my $chunk_index = $nibble_iter->nibble_index();
|
||||
my $hist_sth = $args{hist_sth};
|
||||
|
||||
|
||||
# Warn once per-table for these error codes if the error message
|
||||
@@ -12100,7 +12129,15 @@ sub exec_nibble {
|
||||
}
|
||||
}
|
||||
|
||||
# Success: no warnings, no errors. Return nibble time.
|
||||
# Success: no warnings, no errors. Record and return nibble time.
|
||||
if ( $hist_sth ) {
|
||||
$hist_sth->execute(
|
||||
# WHERE
|
||||
@{$boundary->{lower}}, # upper boundary values
|
||||
@{$boundary->{upper}}, # lower boundary values
|
||||
);
|
||||
}
|
||||
|
||||
return $t_end - $t_start;
|
||||
},
|
||||
);
|
||||
|
||||
@@ -45,15 +45,15 @@ $sb->load_file('master', "$sample/basic_no_fks_innodb.sql");
|
||||
# 2. If table percona.pt_osc created when option present
|
||||
# 2.1.** Default name
|
||||
# 2.2.** Custom name
|
||||
# 2.3.* Second run should not fail or modify this table (except inserting a row for new job)
|
||||
# 2.4.* Case for binary index
|
||||
# 2.3.** Second run should not fail or modify this table (except inserting a row for new job)
|
||||
# 2.4.** Case for binary index
|
||||
# 2.5.** Second run for the binary index
|
||||
# 2.6.** Case for invalid existing table
|
||||
# 2.7.** Case for invalid existing table and binary index
|
||||
# 3. Inserting db, tbl, alter, args
|
||||
# 3.** Inserting db, tbl, alter, args
|
||||
# 4. Updating lower and upper boundaries
|
||||
# 4.1. In situation when pt-osc finishes correctly
|
||||
# 4.1.1. `done` set to 'yes'
|
||||
# 4.1.1.* `done` set to 'yes'
|
||||
# 4.2. In failures
|
||||
# 4.2.1. `done` set to 'no'
|
||||
|
||||
@@ -87,15 +87,32 @@ is(
|
||||
) or diag($output);
|
||||
|
||||
$output = `/tmp/12345/use -N -e "select count(*) from information_schema.tables where TABLE_SCHEMA='percona' and table_name='pt_osc_history'"`;
|
||||
|
||||
is(
|
||||
$output + 0,
|
||||
1,
|
||||
'--history table created when option --history was provided'
|
||||
);
|
||||
|
||||
$output = `/tmp/12345/use -N -e "select count(*) from percona.pt_osc_history where db='pt_osc' and tbl='t' and altr='engine=innodb' and json_extract(args, '\$.alter') = 'engine=innodb' and done='yes'"`;
|
||||
|
||||
is(
|
||||
$output + 0,
|
||||
1,
|
||||
'Initial row with Job ID was inserted into --history table'
|
||||
);
|
||||
|
||||
($output, $exit) = full_output(
|
||||
sub { pt_online_schema_change::main(@args, "$dsn,D=pt_osc,t=t",
|
||||
'--alter', 'engine=innodb', '--execute', '--history') }
|
||||
'--alter', 'engine=innodb', '--execute', '--history', '--chunk-size=4') }
|
||||
);
|
||||
|
||||
$output = `/tmp/12345/use -N -e "select count(*) from percona.pt_osc_history where db='pt_osc' and tbl='t' and altr='engine=innodb' and json_extract(args, '\$.alter') = 'engine=innodb' and done='yes'"`;
|
||||
|
||||
is(
|
||||
$output + 0,
|
||||
2,
|
||||
'--history table updated'
|
||||
);
|
||||
|
||||
is(
|
||||
@@ -138,6 +155,14 @@ like(
|
||||
'--history table created with BLOB data type for boundary columns with --binary-index'
|
||||
);
|
||||
|
||||
$output = `/tmp/12345/use -N -e "select count(*) from percona.pt_osc_history where db='pt_osc' and tbl='t' and altr='engine=innodb' and json_extract(args, '\$.alter') = 'engine=innodb' and done='yes'"`;
|
||||
|
||||
is(
|
||||
$output + 0,
|
||||
1,
|
||||
'Initial row with Job ID was inserted into --history table with --binary-index'
|
||||
);
|
||||
|
||||
($output, $exit) = full_output(
|
||||
sub { pt_online_schema_change::main(@args, "$dsn,D=pt_osc,t=t",
|
||||
'--alter', 'engine=innodb', '--execute', '--history', '--binary-index') }
|
||||
@@ -146,7 +171,7 @@ like(
|
||||
is(
|
||||
$exit,
|
||||
0,
|
||||
'second with option --binary-index finished OK'
|
||||
'second run with option --binary-index finished OK'
|
||||
) or diag($output);
|
||||
|
||||
$output = `/tmp/12345/use -N -e "select count(*) from information_schema.tables where TABLE_SCHEMA='percona' and table_name='pt_osc_history'"`;
|
||||
@@ -156,6 +181,14 @@ is(
|
||||
'--history table was created only once with --binary-index'
|
||||
);
|
||||
|
||||
$output = `/tmp/12345/use -N -e "select count(*) from percona.pt_osc_history where db='pt_osc' and tbl='t' and altr='engine=innodb' and json_extract(args, '\$.alter') = 'engine=innodb' and done='yes'"`;
|
||||
|
||||
is(
|
||||
$output + 0,
|
||||
2,
|
||||
'--history table with --binary-index updated'
|
||||
);
|
||||
|
||||
($output, $exit) = full_output(
|
||||
sub { pt_online_schema_change::main(@args, "$dsn,D=pt_osc,t=t",
|
||||
'--alter', 'engine=innodb', '--execute', '--history') }
|
||||
@@ -200,6 +233,14 @@ is(
|
||||
'Custom --history table created'
|
||||
);
|
||||
|
||||
$output = `/tmp/12345/use -N -e "select count(*) from pt_1717.pt_1717_history where db='pt_osc' and tbl='t' and altr='engine=innodb' and json_extract(args, '\$.alter') = 'engine=innodb' and done='yes'"`;
|
||||
|
||||
is(
|
||||
$output + 0,
|
||||
1,
|
||||
'Initial row with Job ID was inserted custom into --history table'
|
||||
);
|
||||
|
||||
($output, $exit) = full_output(
|
||||
sub { pt_online_schema_change::main(@args, "$dsn,D=pt_osc,t=t",
|
||||
'--alter', 'engine=innodb', '--execute', '--history',
|
||||
@@ -212,13 +253,21 @@ is(
|
||||
'basic test with option --history-table finished OK when table already exists'
|
||||
) or diag($output);
|
||||
|
||||
$output = `/tmp/12345/use -N -e "select count(*) from information_schema.tables where TABLE_SCHEMA='percona' and table_name='pt_osc_history'"`;
|
||||
$output = `/tmp/12345/use -N -e "select count(*) from information_schema.tables where TABLE_SCHEMA='pt_1717' and table_name='pt_1717_history'"`;
|
||||
is(
|
||||
$output + 0,
|
||||
1,
|
||||
'Custom --history table was created only once'
|
||||
);
|
||||
|
||||
$output = `/tmp/12345/use -N -e "select count(*) from pt_1717.pt_1717_history where db='pt_osc' and tbl='t' and altr='engine=innodb' and json_extract(args, '\$.alter') = 'engine=innodb' and done='yes'"`;
|
||||
|
||||
is(
|
||||
$output + 0,
|
||||
2,
|
||||
'Custom --history table updated'
|
||||
);
|
||||
|
||||
# #############################################################################
|
||||
# Done.
|
||||
# #############################################################################
|
||||
|
||||
Reference in New Issue
Block a user