开发者

DBM::Deep: Problems with transactions

开发者 https://www.devze.com 2023-02-13 19:06 出处:网络
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:

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;
0

精彩评论

暂无评论...
验证码 换一张
取 消