Ruby on rails Rails:为什么这个PG事务不起作用?

Ruby on rails Rails:为什么这个PG事务不起作用?,ruby-on-rails,ruby,postgresql,Ruby On Rails,Ruby,Postgresql,我过去在很多应用程序中使用过事务处理,它们总是按预期工作,而现在却不是。我想我只是在想一些显而易见的事情 为什么要创建第一条记录 ActiveRecord::Base.transaction do Order.create!(order_id: 12) raise 'breaking now' Order.create!(order_id: 13) end 我使用的是rails6和postgres12 编辑:实际上现在什么都不起作用了。。。我很困惑。这也不起作用(第一条记录被更新)

我过去在很多应用程序中使用过事务处理,它们总是按预期工作,而现在却不是。我想我只是在想一些显而易见的事情

为什么要创建第一条记录

ActiveRecord::Base.transaction do
  Order.create!(order_id: 12)
  raise 'breaking now'
  Order.create!(order_id: 13)
end
我使用的是
rails6
postgres12

编辑:实际上现在什么都不起作用了。。。我很困惑。这也不起作用(第一条记录被更新)

这个
Order
模型使用的是不同的数据库,但是我在一个使用主数据库的模型上尝试了同样的方法,效果也一样

class Order < ApplicationRecord
  connects_to database: {reading: :orders, writing: :orders}
end
类顺序

Edit:我也从一个新的
rails c
运行这个程序,因此我的代码中没有嵌套事务,我在示例中没有显示。

我相信您正在寻找:

ActiveRecord::Base.connected_to(database: :replica) do
  # you can probably execute plain sql transaction command here and then commit in the end instead of below...
  Order.transaction do 
     # ... all statements that need transaction wrapping from replica
  end
end
此外,
在防止写入时
也很方便:

ActiveRecord::Base.connected_to(role: :orders) do
  Order.connection.while_preventing_writes do
    # will raise because we're blocking writes
    Order.create!
  end
end

ActiveRecord::Base.connected_to(role: :orders) do
  Order.connection.while_preventing_writes do
    # will not raise as we're not writing
    Order.first
  end
end

语句可以来自不同的模型,但在单个块中它们应该属于同一个数据库。 原因是:“事务不跨数据库连接分发”-这超出了ActiveRecord的范围(请参阅:)

如果您确实需要来自不同db连接的跨模型事务,则必须使用文档中提到的解决方法:

Student.transaction do
  Course.transaction do
    course.enroll(student)
    student.units += course.units
  end
end

在这方面,Rails 6.1的一些改进似乎已经如期进行,这些改进可能会使api更简单。如果您想了解更多信息,请参阅本示例和参考资料

您正在连接到另一个数据库,因此应该说
Order.transaction do。。。结束
。巧合的是,当一条ARs被移动到一个单独的数据库时,我遇到了同样的事情。那么,如果我需要编辑事务中的两个模型(位于同一数据库中),会发生什么情况?我曾经能够将模型与
ActiveRecord::Base.transaction混用,所以我假设我仍然需要连接的_中的Base.transaction,对吗?非常感谢你的回答是的。一般来说,正如文档中所说:“虽然对某些活动记录类调用了transaction类方法,但事务块中的对象不一定都是该类的实例。这是因为事务是每个数据库连接,而不是每个模型。”因此,您可以对多个模型使用Order.transaction。如果这看起来很奇怪,您可以创建一个抽象模型(
MyDbBase
),然后从中继承A,B。
Student.transaction do
  Course.transaction do
    course.enroll(student)
    student.units += course.units
  end
end