【问题标题】:Perl and Rose::DB Postgres TransactionsPerl 和 Rose::DB Postgres 事务
【发布时间】:2013-01-29 20:55:06
【问题描述】:

我整天都在为这个问题苦苦挣扎。我想我会在这里问,在我松开所有头发之前。

说明

我将 Perl 5.10.1 与 Rose::DB 和 PostgreSQL 8.4(在 Debian Linux 上)一起使用。

我需要对我的“trans”对象进行一些更改,使其位于单个事务块中(即,更改要么全部写入,要么回滚)。但是,我就是无法让它工作。

我在 AutoCommit ON 和 OFF 的情况下都试过了。

在下面的示例代码中,$db 是在脚本开始时建立的 Rose::DB 连接(使用:my $db = My::DB->new;)。所有 Rose::DB 对象都继承自一个基类 (My::Base)。这个基类有一个用于 DB 连接的可继承子类:

sub init_db
{
    My::DB->new_or_cached
}

DB 连接对象 (My::DB) 包含连接字符串和设置:

_ _PACKAGE_ _->use_private_registry;

_ _PACKAGE_ _->register_db(
    driver          => 'pg',

database        => 'xx',
host            => 'localhost',
username        => 'xx',
password        => 'xx',

    connect_options => {
        AutoCommit      => 0,  -- changed to suit SCENARIO 1 and 2 below
        RaiseError      => 1,
    }
);

场景 1:自动提交关闭

自动提交 0 和 RaiseError 1

my $trans = shift;

eval {
    $trans->...        -- Make changes to object
    $trans->save;

    # die "testing";   -- Cause a rollback using "die"

    $db->commit or die $db->error;
};

if ($@)
{
    warn "aborted: $@";

    eval {
        $db->rollback;
    };
}

回滚案例:​​有效(没有更改写入数据库)

提交案例:失败(没有更改写入数据库)

场景 2:自动提交开启

自动提交 1 和 RaiseError 1

my $trans = shift;

eval {
    $db->begin_work or die $db->error;

    $trans->...        -- Make changes to object
    $trans->save;

    # die "testing";   -- Cause a rollback using "die"

    $db->commit or die $db->error;
};

if ($@)
{
    warn "aborted: $@";

    eval {
        $db->rollback;
    };
}

回滚案例:​​失败(将更改写入数据库)

提交案例:有效(将更改写入数据库)

如果您能提供任何帮助或建议,我们将不胜感激。

提前致谢。

【问题讨论】:

  • 为什么你的场景1没有$db->begin_work?你确定你的两个测试是等价的吗?
  • 在场景 1 中,我们不需要 begin_work,因为我们没有处于 AutoCommit 模式。我们已经在进行交易。 :)
  • 我不确定您的代码是否足以说明发生了什么。您能否发布一个完整的简化示例(包括创建连接)来复制问题?
  • 另一条评论:如果您不小心拥有多个连接(如果提交的连接与具有事务的连接不同),这种行为正是您会得到的。但是,仅从您在此处发布的代码很难说这是否可能。
  • 感谢丹的想法。这绝对是问题所在。如果您可以使用最后一条评论创建答案,我将选择它并添加一些详细信息。干杯!

标签: perl postgresql transactions rose-db-object


【解决方案1】:

您可能打开了多个数据库连接。如果您提交的连接与具有事务的连接不同,则该行为正是人们所期望的。

我建议您重新检查您的程序流程,以确保您只有一个连接。

【讨论】:

  • 嗨,丹,感谢您的建议。这绝对是问题所在。除非您在对象构造函数中指定数据库连接,否则它将建立新连接(或使用现有连接)。解决方案是在构造函数中指定 db 句柄,如下所示: $trans = My::Trans(db => $db);
猜你喜欢
  • 2011-07-06
  • 2010-11-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-01-10
  • 1970-01-01
  • 2012-06-28
相关资源
最近更新 更多