BEGIN { package TransactionMaybe; sub begin { my ($class, $dbh) = @_; my $in_trans = eval { $dbh->begin_work() }; return bless([$dbh, $in_trans], $class); } sub commit { my ($self) = @_; my $dbh = $self->[0]; our $in_trans; local *in_trans = \($self->[1]); $dbh->commit() if $in_trans; $in_trans = 0; } sub DESTROY { my ($dbh, $in_trans) = @$self; local $@; eval { $dbh->rollback() } if $in_trans; } $INC{'TransactionMaybe.pm'} = 1; } { my $transaction = TransactionMaybe->begin($dbh); code_that_touches_db(); $transaction->commit(); }