From 3f90f9ea82c5033f61c300b9d3cd7d1b58e9e7ff Mon Sep 17 00:00:00 2001 From: frank-cizmich Date: Fri, 26 Feb 2016 21:03:18 -0300 Subject: [PATCH] pt-osc generate random table prefix after 10th try --- bin/pt-online-schema-change | 23 +++++++++--- t/pt-online-schema-change/bugs.t | 35 ++++++++++++++++++- .../samples/simple_test_table.sql | 9 +++++ 3 files changed, 62 insertions(+), 5 deletions(-) create mode 100644 t/pt-online-schema-change/samples/simple_test_table.sql diff --git a/bin/pt-online-schema-change b/bin/pt-online-schema-change index 38f78c29..ff17e169 100755 --- a/bin/pt-online-schema-change +++ b/bin/pt-online-schema-change @@ -9546,6 +9546,7 @@ sub main { my $old_tbl; if ( $o->get('swap-tables') ) { + eval { $old_tbl = swap_tables( orig_tbl => $orig_tbl, @@ -10084,7 +10085,7 @@ sub swap_tables { my $prefix = '_'; my $table_name = $orig_tbl->{tbl} . ($args{suffix} || ''); - my $name_tries = 10; # don't try forever + my $name_tries = 20; # don't try forever my $table_exists = qr/table.+?already exists/i; # This sub only works for --execute. Since the options are @@ -10119,6 +10120,16 @@ sub swap_tables { print ts("Swapping tables...\n"); while ( $name_tries-- ) { + + # https://bugs.launchpad.net/percona-toolkit/+bug/1526105 + if ( $name_tries <= 10 ) { # we've already added 10 underscores? + # time to try a small random string + my @chars = ("A".."Z", "0".."9"); + $prefix = ''; + $prefix .= $chars[rand @chars] for 1..6; + $prefix .= "_"; + } + $table_name = $prefix . $table_name; if ( length($table_name) > 64 ) { @@ -10131,6 +10142,7 @@ sub swap_tables { 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, @@ -10150,6 +10162,7 @@ sub swap_tables { # other purposes. $table_exists, ], + operation => "swap_tables", ); }; if ( my $e = $EVAL_ERROR ) { @@ -10169,10 +10182,8 @@ sub swap_tables { name => $q->quote($orig_tbl->{db}, $table_name), }; } - + # 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 ts("Failed to find a unique old table name after " . "serveral attempts.\n"); } @@ -10699,6 +10710,9 @@ sub osc_retry { PTDEBUG && _d('Retry fail:', $error); if ( $ignore_errors ) { + if ($error =~ /table.+?already exists/i) { + PTDEBUG && _d('Aborting retries because of table name conflict. Trying with different name'); + } return 0 if grep { $error =~ $_ } @$ignore_errors; } @@ -10901,6 +10915,7 @@ sub sig_int { exit 1; } + sub _d { my ($package, undef, $line) = caller 0; @_ = map { (my $temp = $_) =~ s/\n/\n# /g; $temp; } diff --git a/t/pt-online-schema-change/bugs.t b/t/pt-online-schema-change/bugs.t index 3a2b0323..c452248e 100644 --- a/t/pt-online-schema-change/bugs.t +++ b/t/pt-online-schema-change/bugs.t @@ -38,7 +38,6 @@ my $output; my $exit_status; my $sample = "t/pt-online-schema-change/samples/"; - # ############################################################################ # https://bugs.launchpad.net/percona-toolkit/+bug/1336734 # pt-online-schema-change 2.2.17 adds --null-to-not-null feature @@ -544,6 +543,40 @@ ok ((!$exit_status && $output =~ /success/i) , "--set-vars sql_mode=\\'a\\\\,b\\ $master_dbh->do("drop database test"); $modes->restore_original_modes(); +# ############################################################################ +# https://bugs.launchpad.net/percona-toolkit/+bug/1526105 +# Not necessarily a bug, but more of an enhancement. +# ############################################################################ + +# We will run pt-osc more than 10 times using --no-drop-old-table and expect +# no errors. + +$sb->load_file('master', "$sample/simple_test_table.sql"); + +my $errors = 0; +my $successes = 0; +for (1..12) { + ($output, $exit_status) = full_output( + sub { pt_online_schema_change::main(@args, + "$master_dsn,D=test,t=test", + "--execute", + "--no-drop-old-table", + "--alter", "ENGINE=InnoDB", + ) }, + ); + if ($exit_status) { + $errors++; + } + if ( $output =~ /Successfully/i ) { + $successes++; + } +} + +ok ( (!$errors && $successes == 12), "Issue #1526105 - no-drop-old-table fails after 10 tries" ); + +$master_dbh->do("DROP DATABASE IF EXISTS test"); + + # ############################################################################# # Done. # ############################################################################# diff --git a/t/pt-online-schema-change/samples/simple_test_table.sql b/t/pt-online-schema-change/samples/simple_test_table.sql new file mode 100644 index 00000000..07cb62a4 --- /dev/null +++ b/t/pt-online-schema-change/samples/simple_test_table.sql @@ -0,0 +1,9 @@ +DROP DATABASE IF EXISTS test; +CREATE DATABASE test; +USE test; +CREATE TABLE `test` ( + `id` int(11) NOT NULL, + `name` varchar(20) DEFAULT NULL, + PRIMARY KEY (`id`) +) ENGINE=InnoDB; +