Question

I've never done transactions (in terms of programming), therefore I don't know if there is something wrong with my script or something else:

#!/usr/bin/env perl
use warnings;
use 5.012;
use DBM::Deep;

my $db = DBM::Deep->new( 'foo.db' );

my $trans = $db->supports( 'transactions' );
say 'Does ', $trans ? '' : 'NOT ', 'support transactions'; 

$db->{key} = 'value';
$db->begin_work;
$db->{key1} = 'value2';
$db->rollback;
$db->{key1} = 'value1';
$db->commit;

Output:

# Does support transactions
# DBM::Deep: Cannot allocate transaction ID at ./perl1.pl line 12

Part of comment:

my $db = DBM::Deep->new( file => 'my.db', num_txns => 1 );

$db->{key} = 'value';
$db->begin_work;
$db->{key1} = 'value2';
$db->rollback;
$db->begin_work;
$db->{key1} = 'value1';
$db->commit;
Was it helpful?

Solution

Sorry about taking so long to answer this question - I only just found it a few days ago. (I'm the maintainer of DBM::Deep.)

The issue is that num_txns is only set when the file is created. (This is because of how the DBM file is laid out on disk.) Once you've created a DBM file, then the num_txns value is read from the file and ignored in the call to new(). So, once you changed your invocation to specify num_txns, it wouldn't help unless you also used a new DBM file.

While I cannot change this behavior without significantly changing how the DBM file structure works (which may be a good idea, but is a huge thing to do), you should have been warned and there should have been better documentation. I have opened https://github.com/robkinyon/dbm-deep/issues/12 to track this problem and the fix(es) for it.

OTHER TIPS

Accoring to the documentation the rollback command ends the transaction.

rollback() This discards the changes done within the transaction to the mainline and ends the transaction.

Therefore you need to start a new transaction after a rollback.

$db->{key} = 'value';
$db->begin_work;
$db->{key1} = 'value2';
$db->rollback;
$db->begin_work;
$db->{key1} = 'value1';
$db->commit;

or you could do something like

sub my_rollback {
  my $db = shift;
  $db->rollback();
  $db->begin_work();
}

$db->{key} = 'value';
$db->begin_work;
$db->{key1} = 'value2';
my_rollback $db;
$db->{key1} = 'value1';
$db->commit;

or with a little black magic, you can keep the OO style

sub my_rollback {
  my $db = shift;
  $db->rollback();
  $db->begin_work();
};
{
  no strict 'refs';
  *{'DBM::Deep::my_rollback'} = \&my_rollback;
}

$db->{key} = 'value';
$db->begin_work;
$db->{key1} = 'value2';
$db->my_rollback;
$db->{key1} = 'value1';
$db->commit;
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top