【问题标题】:DBM::Deep: Problems with transactionsDBM::Deep:事务问题
【发布时间】:2011-02-26 09:46:34
【问题描述】:

我从未做过交易(在编程方面),因此我不知道我的脚本是否有问题或其他问题:

#!/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;

输出:

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

部分评论:

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;

【问题讨论】:

    标签: database perl transactions dbm


    【解决方案1】:

    很抱歉花了这么长时间来回答这个问题 - 我几天前才发现它。 (我是 DBM::Deep 的维护者。)

    问题是num_txns 仅在创建文件时设置。 (这是因为 DBM 文件在磁​​盘上的布局方式。)一旦创建了 DBM 文件,就会从文件中读取 num_txns 值,并在调用 new() 时将其忽略。因此,一旦您将调用更改为指定 num_txns,除非您还使用新的 DBM 文件,否则它将无济于事。

    虽然我无法在不显着更改 DBM 文件结构的工作方式的情况下更改此行为(这可能是个好主意,但要做的事情很大),但您应该得到警告并且应该有更好的文档。我已打开 https://github.com/robkinyon/dbm-deep/issues/12 来跟踪此问题及其修复方法。

    【讨论】:

    • 我还必须将num_txns 设置为 2(或更高)- 1 表示 HEAD + 1 表示事务(如文档中所述)。
    【解决方案2】:

    根据documentation rollback 命令结束事务。

    rollback() 这会丢弃更改 在交易中完成 主线并结束事务。

    因此您需要在回滚后启动新事务。

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

    或者你可以做类似的事情

    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;
    

    或者用一点黑魔法,你可以保持 OO 风格

    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;
    

    【讨论】:

    • 我尝试了您的建议,但再次收到相同的错误消息。
    • 你对 foo.db 有适当的权限吗?尝试不同的文件名或不同的目录
    • 另外,在调用new 时,尝试将线路更改为my $db = DBM::Deep->new(file => 'foo.db', num_txns => 1);,并将num_txns 设置在1 到255 之间
    • @sid_com,这有帮助吗?你还有问题吗?
    • 仍然是相同的错误消息。我将修改后的脚本添加到我的答案中。
    猜你喜欢
    • 1970-01-01
    • 2016-10-24
    • 2016-11-26
    • 1970-01-01
    • 2011-06-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多