示例:
BillingProfile.transaction do
if @billing_profile.save
unless SomeService.do_something # returns false and rollback occurs
raise ActiveRecord::Rollback
end
end
end
@billing_profile.persisted? # Still return true, despite rollback
@billing_profile.id # Is set, despite rollback
为什么@billing_profile的状态不会反映该记录已被回滚?
这是一个问题,因为在回滚后无法创建记录。
答案 0 :(得分:3)
原来这是ActiveRecord(Rails 4)中的一个错误:https://github.com/rails/rails/issues/13744
现在已经修复了。
答案 1 :(得分:0)
我对交易如何运作感兴趣。您的具体方案在docs中说明。引用文档
事务调用可以嵌套。默认情况下,这会使所有数据库 嵌套事务块中的语句成为父项的一部分 交易。例如,以下行为可能会令人惊讶:
User.transaction do User.create(username: 'Kotori') User.transaction do User.create(username: 'Nemu') raise ActiveRecord::Rollback end end
创造了“Kotori”和“Nemu”。 Reason是ActiveRecord :: Rollback 嵌套块中的异常不会发出ROLLBACK。既然这些 父块执行的事务块中捕获异常 没有看到它,真正的交易已经提交。
为了获得嵌套事务的ROLLBACK,您可能会要求 通过传递requires_new:true来实现真正的子事务。如果有的话 错了,数据库回滚到子事务的开头 没有回滚父事务。如果我们将它添加到 上一个例子:
User.transaction do User.create(username: 'Kotori') User.transaction(requires_new: true) do User.create(username: 'Nemu') raise ActiveRecord::Rollback end end
仅创建“Kotori”。这适用于MySQL和PostgreSQL。 sqlite3的 版本> ='3.6.8'也支持它。
大多数数据库不支持真正的嵌套事务。在那个时间 写作,我们所知道的唯一支持true的数据库 嵌套事务,是MS-SQL。因此,Active Record 通过在MySQL和MySQL上使用保存点来模拟嵌套事务 PostgreSQL的。请参阅dev.mysql.com/doc/refman/5.6/en/savepoint.html 有关保存点的更多信息。