#!/usr/bin/perl -w # written by philo vivero - 2005 # released under the terms of the GNU GPL use strict; my $usage = "usage: $0 \n" . " ipAddress IP address of MySQLd to keep starting slave on\n" . " port Port MySQLd is listening on\n" . "\n" . "Will connect to the MySQLd and keep moving past borked transactions\n" . "or retrying them (depending on configuration) until the replication is\n" . "back on track for several seconds.\n" ; my $login = 'root'; my $password = ''; my $hostNamePort = $ARGV[0]; my $hostName; my $hostPort; if ($hostNamePort && $hostNamePort =~ /^(.+?):(.+)$/) { $hostName = $1; $hostPort = $2; } else { die $usage; } # define here the types of error codes we can deal with my $skipCodeVals; $skipCodeVals->{1050} = "Table you're adding already exists"; $skipCodeVals->{1051} = "Table you're dropping already gone"; $skipCodeVals->{1060} = "Column you're adding already exists"; $skipCodeVals->{1061} = "Index you're adding already exists"; $skipCodeVals->{1062} = "Primary key of row you're inserting already exists"; $skipCodeVals->{1091} = "Index/column you're dropping doesn't exist"; my $retryCodeVals; $retryCodeVals->{1205} = "Lock Wait Timeout on transaction"; # build a list of known error codes this script can deal with my $errCodesList = ""; foreach my $key (keys %{$skipCodeVals}) { $errCodesList .= "$key|"; } foreach my $key (keys %{$retryCodeVals}) { $errCodesList .= "$key|"; } $errCodesList =~ s/\|$//; open (SQLCMD, "| mysql -P $hostPort -h $hostName -p$password -u$login"); my $errNo = getErrNo(); while ($errNo) { if ($errNo !~ /$errCodesList/) { print " - Can't deal with errNo=$errNo! Aborting fatally dead.\n"; exit 255; } # errors to skip past if (defined $skipCodeVals->{$errNo}) { print " - Skipping past error: $errNo ($skipCodeVals->{$errNo})\n"; print SQLCMD "set global sql_slave_skip_counter = 1;\n"; print SQLCMD "slave start;\n"; } # errors to retry if (defined $retryCodeVals->{$errNo}) { print " - Retrying transaction for error: $errNo ($retryCodeVals->{$errNo})\n"; print SQLCMD "slave start;\n"; } $errNo = getErrNo(); unless ($errNo) { print " - Sleeping 2 seconds to see if slave dies again.\n"; sleep 2; $errNo = getErrNo(); } } close SQLCMD; # ----------------------------------------------------- # ----------------------------------------------------- # ----------------------------------------------------- sub getErrNo { my ($err, $errNo); $err = `mysql -P $hostPort -h $hostName -u$login -p$password -e "show slave status\\G"| grep Last_Errno`; if ($err =~ /: (\d+)/) { $errNo = $1; } return $errNo; }