KDOC 689: Railsのネストしたtransactionでは内側のActiveRecord::Rollbackが無視される

この文書のステータス

  • 作成
    • 2026-10-18 貴島
  • レビュー
    • 2026-10-18 貴島

概要

Railsで transaction をネストすると、既定では内側のブロックは外側のトランザクションに合流する。内側で raise ActiveRecord::Rollback してもROLLBACKは発行されず、外側はそのままコミットされる。 ActiveRecord::Rollback は transaction ブロックが受け止めて外へ投げ直さないので、外側には届かない。ほかの例外は外側まで伝わり、外側ごとロールバックされる。

内側だけを戻したいときは requires_new: true を付けると、SAVEPOINTを使ったサブトランザクションになる。

One exception is the ActiveRecord::Rollback exception, which will trigger a ROLLBACK when raised, but not be re-raised by the transaction block. Any other exception will be re-raised.

transaction calls can be nested. By default, this makes all database statements in the nested transaction block become part of the parent transaction.

Reason is the ActiveRecord::Rollback exception in the nested block does not issue a ROLLBACK. Since these exceptions are captured in transaction blocks, the parent block does not see it and the real transaction is committed.

In order to get a ROLLBACK for the nested transaction you may ask for a real sub-transaction by passing requires_new: true.

Active Record emulates nested transactions by using savepoints.

ActiveRecord::Transactions::ClassMethods (Rails 8.1.4)

関連