The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.

NAME

DBI::Transaction - advanced object-oriented support for database transactions

DOCUMENTATION STATE

Docs are incomplete and wrong!

PURPOSE

DBI::Transaction allows several transactions to be embedded inside each other (but see CAVEATS about problems with rolling back).

This is inevitable for modular development to allow modules automatically utilize transactions.

SYNOPSIS

 use DBI::Transaction;

 $transaction = DBI::Transaction->new($dbh);

 # ...

 $transaction->commit;
 # or
 $transaction->rollback; # See below for caveats.

CAVEATS

  • See below about destroying.

  • When several transactions are embedded in each other, attempt to rollback an inner transaction may throw an CannotRollback.

    In this case you should rollback the entire upper level transaction.

  • At least in MySQL (DBD::mysql(3)) driver, connectiong with AutoCommit=>1 causes this module to commit three times rather than once! This is a bug in DBD::mysql(3). So use AutoCommit=>0 and manually commit the uttermost transaction:

      $transaction = DBI::Transaction->new($dbh);
      # ...
      $transaction->commit;
      $dbh->commit;

    $dbh->commit should not be called if was rollback CannotRollback... XXX. So, upper level transaction should be handled so (in MySQL):

      $transaction = DBI::Transaction->new($dbh);
      # ...
      $transaction->commit;
      $dbh->disconnect;
  • When a library routine may call rollback() method from this class, this routine documentation should document that it calls it. The caller must trap the DBI::Transaction::CannotRollback, and (usually) roll back parent transactions in response on this CannotRollback.

DESTROYING

A transaction must be explicitly either commited or rolled back. Otherwise destroying it will throw an CannotRollback (see below).

Destroying a not finished transaction is considered as an error (TODO: Shouldn't we make it fatal?) and it meant only for debugging.

Destroying a not finished transaction attempts to roll back it before throwing the CannotRollback. But roll back may fail for the case of a subtransaction. (This useally signifies the need to roll back its parent transaction.)

DESCRIPTION

See DBI(3) for descriptions of database handles ($dbh).

DBI::Transaction->new()
 $transaction = DBI::Transaction->new($dbh);

This starts a transaction.

commit()

Commits and finishes the transaction. Returns true on success.

rollback()

Rolls back and finishes the transaction. Returns true on success.

is_finished()

Returns false after commit or rollback,

DBI::Transaction::CannotRollback

Exception for rolling back a transaction failed because it was a subtransaction of an other transaction.

RATIONALE

This module may seem to be over-sophisticated as we can use just

  local $dbh->{AutoCommit} = 0;

But because of DBI(3) design deficiencies, we really need this module and it cannot be made simpler than it is without making it broken (at least without changing DBI(3) itself).

SUGGESTIONS

DESTROY of not finished transaction is only a debugging mean. You should not rely on its behavior.

If some routine may call $transaction->rollback() you should wrap this routine with "eval" unless it is the uttermost level transaction.

TODO

Docs are incomplete.

"Rollback to savepoint" feature of some SQL engines (e.g. MySQL) is not utilized.

AUTHOR

The original author Victor Porton <porton@ex-code.com> will gladly hear your bug reports.

Module's homepage: http://ex-code.com/dbi-transactions/

LICENSE

General Public License version 2 (see also module's homepage).

SEE ALSO

DBI(3), DBI::Transaction::Repeated(3)