gpt4 book ai didi

mysql - 为什么 Rails 忽略(伪)嵌套事务中的回滚?

转载 作者:IT老高 更新时间:2023-10-28 23:58:05 28 4
gpt4 key购买 nike

根据文档 ActiveRecord::Transactions::ClassMethods ,非新嵌套事务将忽略回滚。来自文档:

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

raise ActiveRecord::Rollback 被忽略,因为它在子事务中(或者更确切地说,它仍在父事务中,而不是它自己的)。我不明白为什么两者都会忽略回滚调用?我可以看到,由于子“事务”不是真正的事务,它不会回滚“Nemu” block ,但为什么它不会触发父级的回滚?子事务是否以某种方式隐藏了回滚?

换句话说,为什么似乎无法从嵌套子级中回滚父事务?

最佳答案

实际上,这正是 Nested Transactions 的设计初衷。我引用 oracle 文档:

A nested transaction is used to provide a transactional guarantee for a subset of operations performed within the scope of a larger transaction. Doing this allows you to commit and abort the subset of operations independently of the larger transaction.

因此,常规嵌套事务中的子事务对他或其他子事务或父事务(更大的事务)的行为没有发言权,除了改变相互数据或因异常而失败。

但是您可以通过使用 rails docs 中所述的子交易 功能,授予他(子交易)一个非常有限的投票机会来决定他的命运。通过传递 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”。因为强大的‘音梦’之子选择了默默地死去。

关于嵌套交易规则的更多细节(oracle docs)

更新:

为了更好地理解为什么 rails nested transactions 以这种方式工作,您需要更多地了解嵌套事务在 DB 级别的工作方式,我引用自 rails api docs :

Most databases don’t support true nested transactions ...In order to get around this problem, #transaction will emulate the effect of nested transactions, by using savepoints: http://dev.mysql.com/doc/refman/5.0/en/savepoint.html

好的,那么文档描述了上述两种情况下嵌套事务的行为,如下所示:

如果是嵌套调用,#transaction将表现如下:

  • 该 block 将在不执行任何操作的情况下运行。 block 内发生的所有数据库语句都有效地附加到已经打开的数据库事务。

  • 但是,如果设置了 :requires_new,该 block 将被包装在充当子事务的数据库保存点中。

我想象小心,只想象:

option(1)(without requires_new)如果您使用的 DBMS 完全支持 nested transactions 或者您满意nested_attributes

的“假”行为

option(2) 是为了支持 savepoint 解决方法(如果您不这样做的话)。

关于mysql - 为什么 Rails 忽略(伪)嵌套事务中的回滚?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22413599/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com