【发布时间】: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