ap / DBIx-Connector

Fast, safe DBI connection and transaction management
https://metacpan.org/release/DBIx-Connector
40 stars 14 forks source link

Add Deadlock Retries #34

Open theory opened 11 years ago

theory commented 11 years ago

Should work for serialization failures, too. See this blog post for details and discussion (especially the comments from Kevin Grittner).

Perlover commented 11 years ago

+1 I very want to have fixup mode for deadlocks in InnoDB! :)

matthewlenz commented 4 years ago

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!';
};