~percona-toolkit-dev/percona-toolkit/release-2.2.3

« back to all changes in this revision

Viewing changes to bin/pt-online-schema-change

First working enhanced --set-vars in pt-osc: no "default: ...", instead default values are under MAGIC_set_vars, picked up by OptionParser and passed to DSNParser.  Also increaes --retries from 3 to 10.  TODO: more testing.

Show diffs side-by-side

added added

removed removed

Lines of Context:
80
80
 
81
81
use List::Util qw(max);
82
82
use Getopt::Long;
 
83
use Data::Dumper;
83
84
 
84
85
my $POD_link_re = '[LC]<"?([^">]+)"?>';
85
86
 
1063
1064
   );
1064
1065
};
1065
1066
 
 
1067
sub set_vars {
 
1068
   my ($self, $file) = @_;
 
1069
   $file ||= $self->{file} || __FILE__;
 
1070
 
 
1071
   my %user_vars;
 
1072
   my $user_vars = $self->has('set-vars') ? $self->get('set-vars') : undef;
 
1073
   if ( $user_vars ) {
 
1074
      foreach my $var_val ( @$user_vars ) {
 
1075
         my ($var, $val) = $var_val =~ m/([^\s=]+)=(\S+)/;
 
1076
         die "Invalid --set-vars value: $var_val\n" unless $var && $val;
 
1077
         $user_vars{$var} = {
 
1078
            val     => $val,
 
1079
            default => 0,
 
1080
         };
 
1081
      }
 
1082
   }
 
1083
 
 
1084
   my %default_vars;
 
1085
   my $default_vars = $self->read_para_after($file, qr/MAGIC_set_vars/);
 
1086
   if ( $default_vars ) {
 
1087
      %default_vars = map {
 
1088
         my $var_val = $_;
 
1089
         my ($var, $val) = $var_val =~ m/([^\s=]+)=(\S+)/;
 
1090
         die "Invalid --set-vars value: $var_val\n" unless $var && $val;
 
1091
         $var => {
 
1092
            val     => $val,
 
1093
            default => 1,
 
1094
         };
 
1095
      } split("\n", $default_vars);
 
1096
   }
 
1097
 
 
1098
   my %vars = (
 
1099
      %default_vars, # first the tool's defaults
 
1100
      %user_vars,    # then the user's which overwrite the defaults
 
1101
   );
 
1102
   PTDEBUG && _d('--set-vars:', Dumper(\%vars));
 
1103
   return \%vars;
 
1104
}
 
1105
 
1066
1106
sub _d {
1067
1107
   my ($package, undef, $line) = caller 0;
1068
1108
   @_ = map { (my $temp = $_) =~ s/\n/\n# /g; $temp; }
2193
2233
 
2194
2234
      if ( my ($charset) = $cxn_string =~ m/charset=([\w]+)/ ) {
2195
2235
         $sql = qq{/*!40101 SET NAMES "$charset"*/};
2196
 
         PTDEBUG && _d($dbh, ':', $sql);
 
2236
         PTDEBUG && _d($dbh, $sql);
2197
2237
         eval { $dbh->do($sql) };
2198
2238
         if ( $EVAL_ERROR ) {
2199
2239
            die "Error setting NAMES to $charset: $EVAL_ERROR";
2208
2248
         }
2209
2249
      }
2210
2250
 
2211
 
      if ( my $var = $self->prop('set-vars') ) {
2212
 
         $sql = "SET $var";
2213
 
         PTDEBUG && _d($dbh, ':', $sql);
2214
 
         eval { $dbh->do($sql) };
2215
 
         if ( $EVAL_ERROR ) {
2216
 
            die "Error setting $var: $EVAL_ERROR";
2217
 
         }
 
2251
      if ( my $vars = $self->prop('set-vars') ) {
 
2252
         $self->set_vars($dbh, $vars);
2218
2253
      }
2219
2254
 
2220
2255
      $sql = 'SET @@SQL_QUOTE_SHOW_CREATE = 1'
2289
2324
   return \%new_dsn;
2290
2325
}
2291
2326
 
 
2327
sub set_vars {
 
2328
   my ($self, $dbh, $vars) = @_;
 
2329
 
 
2330
   foreach my $var ( sort keys %$vars ) {
 
2331
      my $val = $vars->{$var}->{val};
 
2332
 
 
2333
      (my $quoted_var = $var) =~ s/_/\\_/;
 
2334
      my ($var_exists, $current_val);
 
2335
      eval {
 
2336
         ($var_exists, $current_val) = $dbh->selectrow_array(
 
2337
            "SHOW VARIABLES LIKE '$quoted_var'");
 
2338
      };
 
2339
      my $e = $EVAL_ERROR;
 
2340
      if ( $e ) {
 
2341
         PTDEBUG && _d($e);
 
2342
      }
 
2343
 
 
2344
      if ( $vars->{$var}->{default} && !$var_exists ) {
 
2345
         PTDEBUG && _d('Not setting default var', $var,
 
2346
            'because it does not exist');
 
2347
         next;
 
2348
      }
 
2349
 
 
2350
      if ( $current_val && $current_val eq $val ) {
 
2351
         PTDEBUG && _d('Not setting var', $var, 'because its value',
 
2352
            'is already', $val);
 
2353
         next;
 
2354
      }
 
2355
 
 
2356
      my $sql = "SET SESSION $var=$val";
 
2357
      PTDEBUG && _d($dbh, $sql);
 
2358
      eval { $dbh->do($sql) };
 
2359
      if ( my $set_error = $EVAL_ERROR ) {
 
2360
         chomp($set_error);
 
2361
         $set_error =~ s/ at \S+ line \d+//;
 
2362
         my $msg = "Error setting $var: $set_error";
 
2363
         if ( $current_val ) {
 
2364
            $msg .= "  The current value for $var is $current_val.  "
 
2365
                  . "If the variable is read only (not dynamic), specify "
 
2366
                  . "--set-vars $var=$current_val to avoid this warning, "
 
2367
                  . "else manually set the variable and restart MySQL.";
 
2368
         }
 
2369
         warn $msg . "\n\n";
 
2370
      }
 
2371
   }
 
2372
 
 
2373
   return; 
 
2374
}
 
2375
 
2292
2376
sub _d {
2293
2377
   my ($package, undef, $line) = caller 0;
2294
2378
   @_ = map { (my $temp = $_) =~ s/\n/\n# /g; $temp; }
7876
7960
   $o->get_opts();
7877
7961
 
7878
7962
   my $dp = $o->DSNParser();
7879
 
   $dp->prop('set-vars', $o->get('set-vars'));
 
7963
   $dp->prop('set-vars', $o->set_vars());
7880
7964
 
7881
7965
   # The original table, i.e. the one being altered, must be specified
7882
7966
   # on the command line via the DSN.
7981
8065
   # ########################################################################
7982
8066
   my $set_on_connect = sub {
7983
8067
      my ($dbh) = @_;
7984
 
 
7985
 
      # See the same code in pt-table-checksum.
7986
 
      my $lock_wait_timeout = $o->get('lock-wait-timeout');
7987
 
      my $set_lwt = "SET SESSION innodb_lock_wait_timeout=$lock_wait_timeout";
7988
 
      PTDEBUG && _d($set_lwt);
7989
 
      eval {
7990
 
         $dbh->do($set_lwt);
7991
 
      };
7992
 
      if ( $EVAL_ERROR ) {
7993
 
         PTDEBUG && _d($EVAL_ERROR);
7994
 
         # Get the server's current value.
7995
 
         my $sql = "SHOW SESSION VARIABLES LIKE 'innodb_lock_wait_timeout'";
7996
 
         PTDEBUG && _d($dbh, $sql);
7997
 
         my (undef, $curr_lwt) = $dbh->selectrow_array($sql);
7998
 
         PTDEBUG && _d('innodb_lock_wait_timeout on server:', $curr_lwt);
7999
 
         if ( !defined $curr_lwt ) {
8000
 
            PTDEBUG && _d('innodb_lock_wait_timeout does not exist;',
8001
 
               'InnoDB is probably disabled');
8002
 
         }
8003
 
         elsif ( $curr_lwt > $lock_wait_timeout ) { 
8004
 
            warn "Failed to $set_lwt: $EVAL_ERROR\n"
8005
 
               . "The current innodb_lock_wait_timeout value "
8006
 
               . "$curr_lwt is greater than the --lock-wait-timeout "
8007
 
               . "value $lock_wait_timeout and the variable cannot be "
8008
 
               . "changed.  innodb_lock_wait_timeout is only dynamic when "
8009
 
               . "using the InnoDB plugin.  To prevent this warning, either "
8010
 
               . "specify --lock-wait-time=$curr_lwt, or manually set "
8011
 
               . "innodb_lock_wait_timeout to a value less than or equal "
8012
 
               . "to $lock_wait_timeout and restart MySQL.\n";
8013
 
         }
8014
 
      }
 
8068
      return;
8015
8069
   };
8016
8070
 
8017
8071
   # Do not call "new Cxn(" directly; use this sub so that set_on_connect
10769
10823
 
10770
10824
Connect to host.
10771
10825
 
10772
 
=item --lock-wait-timeout
10773
 
 
10774
 
type: int; default: 1
10775
 
 
10776
 
Set the session value of C<innodb_lock_wait_timeout>.  This option helps guard
10777
 
against long lock waits if the data-copy queries become slow for some reason.
10778
 
Setting this option dynamically requires the InnoDB plugin, so this works only
10779
 
on newer InnoDB and MySQL versions.  If the setting's current value is greater
10780
 
than the specified value, and the tool cannot set the value as desired, then it
10781
 
prints a warning. If the tool cannot set the value but the current value is less
10782
 
than or equal to the desired value, there is no error.
10783
 
 
10784
10826
=item --max-lag
10785
10827
 
10786
10828
type: time; default: 1s
10919
10961
 
10920
10962
=item --retries
10921
10963
 
10922
 
type: int; default: 3
 
10964
type: int; default: 10
10923
10965
 
10924
10966
Retry a chunk this many times when there is a nonfatal error.  Nonfatal errors
10925
10967
are problems such as a lock wait timeout or the query being killed. This option
10927
10969
 
10928
10970
=item --set-vars
10929
10971
 
10930
 
type: string; default: wait_timeout=10000
10931
 
 
10932
 
Set these MySQL variables.  Immediately after connecting to MySQL, this string
10933
 
will be appended to SET and executed.
 
10972
type: Array
 
10973
 
 
10974
Set the MySQL variables in this comma-separated list of C<variable=value> pairs.
 
10975
 
 
10976
By default, the tool sets:
 
10977
 
 
10978
=for comment ignore-pt-internal-value
 
10979
MAGIC_set_vars
 
10980
 
 
10981
   wait_timeout=10000
 
10982
   innodb_lock_wait_timeout=1
 
10983
   lock_wait_timeout=60
 
10984
 
 
10985
Variables specified on the command line override these defaults.  For
 
10986
example, specifying C<--set-vars wait_timeout=500> overrides the default
 
10987
value of C<10000>.
 
10988
 
 
10989
The tool prints a warning and continues if a variable cannot be set.
10934
10990
 
10935
10991
=item --socket
10936
10992