diff --git a/modules/Bio/EnsEMBL/Utils/SqlHelper.pm b/modules/Bio/EnsEMBL/Utils/SqlHelper.pm index 62357577bef61dfc2ee3816f14e783c1f742c1ab..4c5052ec5ab4f5bcc4c2701b6be347bb676c5db3 100644 --- a/modules/Bio/EnsEMBL/Utils/SqlHelper.pm +++ b/modules/Bio/EnsEMBL/Utils/SqlHelper.pm @@ -468,11 +468,13 @@ previous setting. If your DBI/DBD driver does not support manual commits then this code will break. The code will turn off the C<disconnect_when_idle()> method to allow transactions to work as expected. -If the connection given already had AutoCommit off we will issue a rollback -before handing the connection into the closure. This ensures the connection -contains as fresh information from the database as possible. An effect of -using REPEATABLE READ transaction isolation (InnoDB's default) is that -your data is as fresh as when you started your current transaction. To +All connections are issued a C<begin_work()> call on the DBI handle which +informs the target engine we are starting a transaction. Giving this method +a connection already in a transaction will cause an error to be raised and +the abortion of the running transaction. + +An effect of using REPEATABLE READ transaction isolation (InnoDB's default) +is that your data is as fresh as when you started your current transaction. To ensure the freshest data use C<SELECT ... from ... LOCK IN SHARE MODE> or C<SELECT ... from ... LOCK FOR UPDATE> if you are going to issue updates. @@ -496,6 +498,9 @@ sub transaction { my $original_dwi; my $ac; + my $error; + my $result; + #If we were already in a transaction then we do not do any management of the #session & wait for the parent transaction(s) to finish my $perform_transaction = $self->_perform_transaction_code(); @@ -503,19 +508,18 @@ sub transaction { $original_dwi = $dbc->disconnect_when_inactive(); $ac = $dbc->db_handle()->{'AutoCommit'}; $dbc->db_handle()->{'AutoCommit'} = 0; - #Issue a rollback as a signal for a fresh transaction if AutoCommit was off - $dbc->db_handle()->rollback() if(! $ac); - $self->_enable_transaction(); + eval { $dbc->db_handle()->begin_work() }; + $error = $@ if $@; + $self->_enable_transaction() unless $error; } - my $error; - my $result; - - eval { - $result = $callback->($dbc); - $dbc->db_handle()->commit() if $perform_transaction; - }; - $error = $@; + if(!$error) { + eval { + $result = $callback->($dbc); + $dbc->db_handle()->commit() if $perform_transaction; + }; + $error = $@; + } if($perform_transaction) { if($error) {