eval { local $dbh->{AutoCommit} = 0; }; $self->{_can_do_transactions} = $@ ? 0 : 1; #### $self->{_can_do_transactions} = eval { local $dbh->{AutoCommit} = 0; 1 }; #### $self->{_can_do_transactions} = eval { $dbh->begin_work(); $dbh->rollback() }; #### my $in_trans = eval { $dbh->begin_work() }; if (!eval { code_that_touches_db(); $dbh->commit() if $in_trans; 1 }) { my $msg = $@; eval { $dbh->rollback() } if $in_trans; die $msg; } #### use Sub::ScopeFinalizer qw( scope_finalizer ); { my $in_trans = eval { $dbh->begin_work() }; my $pending_rollback = scope_finalizer { local $@; eval { $dbh->rollback() } if $in_trans; }; code_that_touches_db(); $pending_rollback->disable(); $dbh->commit() if $in_trans; } #### 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(); }