Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/powerbi/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ruby on rails 具有多个数据库的Rails 3 ActiveRecord嵌套事务_Ruby On Rails_Ruby On Rails 3_Transactions - Fatal编程技术网

Ruby on rails 具有多个数据库的Rails 3 ActiveRecord嵌套事务

Ruby on rails 具有多个数据库的Rails 3 ActiveRecord嵌套事务,ruby-on-rails,ruby-on-rails-3,transactions,Ruby On Rails,Ruby On Rails 3,Transactions,根据rails文档,涉及多个数据库的嵌套事务应该可以工作: User.transaction do User.create(:username => 'Kotori') User.transaction(:requires_new => true) do User.create(:username => 'Nemu') raise ActiveRecord::Rollback end end 如何在嵌套事务中进行回滚传播,以便父事务也回滚 首先,您

根据rails文档,涉及多个数据库的嵌套事务应该可以工作:

User.transaction do
  User.create(:username => 'Kotori')
  User.transaction(:requires_new => true) do
    User.create(:username => 'Nemu')
    raise ActiveRecord::Rollback
  end
end
如何在嵌套事务中进行回滚传播,以便父事务也回滚


首先,您的代码不使用多个数据库。两者都使用来自客户端模型的连接

其次,您没有指定DBMS。不同的数据库驱动程序具有不同的属性,并且不是所有的驱动程序都实现嵌套事务。您使用的是哪个数据库

我只是做了你想做的,我用了两个postgres数据库。仅抛出ActiveRecord::Rollback将退出封闭事务,但不会引发进一步的异常。我想确保如果嵌套事务失败,则回滚外部事务。 因此,我捕获内部事务中的任何异常,然后从那里进行回滚

注意:帐户和用户模型使用不同的数据库,尽管它们都运行在同一个Postgres实例中。另外,如果省略begin rescue子句,那么是的,代码将回滚两个数据库,但在外部事务结束后,将出现一个异常,即展开堆栈。最后,我认为如果提交外部事务时出现问题,那么内部事务将不会回滚。就我而言,这不是问题。您可能希望将DB1代码包装在嵌套事务中,并在启动DB2事务之前提交它

Account.transaction do
  begin
    acc = Account.do_something_to_accounts
    User.transaction do
      User.do_something_to_users
    end
  rescue => e
    raise ActiveRecord::Rollback
  end
end

乔纳森所说的是正确的,但他的代码示例并不完全正确

为了在两个数据库之间取消事务,您需要检测嵌套事务何时将在没有外部事务的情况下回滚。标准异常将是未捕获的,并导致两个事务回滚。然而,
ActiveRecord#transaction
块将从
ActiveRecord::rollback
中静默地解救和回滚,因此解决方案需要在嵌套事务的每个级别(本例中仅为1级)中检测这种情况并传播它

一种解决方案可能是:

Account.transaction.do
acc=账户。对账户做些什么
是否应该回滚=false
User.transaction.do
开始
User.do\u某事\u对\u用户
rescue ActiveRecord::回滚
是否应该回滚=true
raise ActiveRecord::回滚
结束
结束
如果应该回滚,则引发ActiveRecord::回滚
结束
另一种实现方式:

类嵌套TransactionRollback
编辑: 您还可以尝试构建一个通用解决方案,如下所示:


类DistributedBrollback