ryota21silvaの技術ブログ

Funna(ふんな)の技術ブログ

これまで学んだ技術の備忘録。未来の自分が救われることを信じて

DBの整合性を守るtransactionについて

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

参考資料

book.impress.co.jp