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.
関連
- 前提: KDOC 334: トランザクションはネストできない。ORMがネストをSAVEPOINTで真似ていること