DBM::Deep: Problems with transactions
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;
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.
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;
精彩评论