Open theory opened 11 years ago
+1 I very want to have fixup mode for deadlocks in InnoDB! :)
How terrible is this (uses Try::Tiny::Retry)? The only obvious issue I see is that your code already reattempts connections for some of those exceptions so the total number of tries will be more.
sub retry_txn {
my ($self, $code, $rethrow) = @_;
my $dbc = $self->get_dbc();
return retry {
$dbc->txn(fixup => $code);
} delay {
return if $_[0] >= 10;
sleep 0.5*$_[0];
} on_retry {
warn "Retrying transaction.";
} retry_if {
my $err = $_;
$err = $err->error
if (eval { $err->isa('DBIx::Connector::RollbackError') });
$err =~ /deadlock|lost connection|gone away|can't connect/i;
} catch {
if ($rethrow) {
my $err = $_;
$err = $err->error
if (eval { $err->isa('DBIx::Connector::RollbackError') });
die $err;
}
};
}
Usage would be something like:
$app->retry_txn(sub {
$app->some_sql_actions();
});
or
try {
$app->retry_txn(sub {
$app->some_sql_actions();
}, 1);
} catch {
warn 'oh Snap!';
};
Should work for serialization failures, too. See this blog post for details and discussion (especially the comments from Kevin Grittner).