为什么坚持?在ActiveRecord::回滚后返回true



示例:

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的状态不反映该记录已回滚?

这是一个问题,因为记录在回滚后无法创建。

原来这是ActiveRecord(Rails 4)中的一个错误:https://github.com/rails/rails/issues/13744

现在已经修复。

我对事务的工作方式很感兴趣。文档中解释了您的具体场景。引用文档

事务调用可以嵌套。默认情况下,这会使所有数据库嵌套事务块中的语句成为父级的一部分交易例如,以下行为可能令人惊讶:

User.transaction do
User.create(username: 'Kotori')
User.transaction do
User.create(username: 'Nemu')
raise ActiveRecord::Rollback
end
end

创造了"Kotori"one_answers"Nemu"。原因是ActiveRecord::回滚嵌套块中的异常不会发出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和PostgreSQL。请参阅dev.mysql.com/doc/refman/5.6/en/savepoint.html有关保存点的详细信息。

相关内容

  • 没有找到相关文章

最新更新