transactionとは
複数のSQL文をtransactionという一つの単位にまとめることで、それぞれのSQLの処理が全て成功した場合にのみ、SQLの処理結果をDBに反映するよというもの。
典型的なのは銀行口座の例で、
①A口座の残高から¥1,000引き落とす
②B口座の残高を¥1,000増やす
という2つの処理を1つのtransactionにまとめる。
これをtransactionにしないと、①の処理は成功したけど②の処理が途中で中断してしまった、という時に、DBの整合性を守れないし、現実世界でトラブルとなることは容易に想像がつく。
Railsのtransactionの例
(app/controllers/admin/articles/article_blocks_controller.rb) Article.transaction do @article.body = @article.build_body(self) @article.save! end
上記の例では
@article.body = @article.build_body(self)
と
@article.save!
がtransactionになっている。
2つの処理のうち、どちらかが失敗すると、ブロック内(do~end)のSQL処理を全部ロールバックする。
そしてRailsでは、ロールバックが発火するには、「例外」の発生が必要。
Railsでは
- saveは保存できない時にfalseを返す。
- save!は保存できない時にActiveRecord::RecordInvalidという処理を返す。
なので、save!が失敗した時にロールバックが発火してくれる。
ついでにSQLについて殴り書き
transactionの開始と終了には以下のパターンがある(他にあるんかな?)。
- BEGIN〜COMMIT
- BEGIN〜ROLLBACK