ロールバック
Rollback
概要(サマリー)
ロールバックとは、何かの処理の途中でエラーが起きたときに、それまでのすべての変更をなかったことにして、実行前の「元の安全な状態に戻す(巻き戻す)」操作である。
たとえば、銀行のATMで口座Aから口座Bへ1万円を送金する処理を考えてみよう。
この処理は以下の2ステップで行われる。
- 口座Aから1万円を引き出す(マイナス1万円)。
- 口座Bに1万円を入金する(プラス1万円)。
もし、ステップ1が完了した直後に、ATMやネットワークの不具合でシステムが停止してしまったらどうなるだろうか。あなたの口座Aからは1万円が引かれたのに、相手の口座Bには届いておらず、1万円が宇宙の彼方に消えてしまうことになる。
このようなデータ崩壊を防ぐため、データベースには「途中で失敗したら、1つ目のステップもすべてなかったことにして、開始前の状態に完全に巻き戻す」というルールが備わっている。この巻き戻しを「ロールバック」と呼ぶ。
詳細解説
データベースのトランザクションにおけるロールバック
データベースにおいて、関連する複数の処理を「これで1つのまとまり(絶対に分割できない一連の処理)」として扱う単位を トランザクション(Transaction) と呼ぶ。
トランザクションの終わりには、以下のいずれかの操作が実行される。
- コミット(Commit): すべてのステップが成功したので、変更を確定して保存する。
- ロールバック(Rollback): 途中で1つでも失敗したので、変更をすべて破棄して開始前の状態に戻す。
これにより、データの不整合(引き落とされたのに届いていない等)を防ぎやすくなり、複数の処理を安全なまとまりとして扱える。
その他のロールバック(Gitやインフラ)
ロールバックという言葉は、データベース以外でも「元に戻す」という意味で広く使われる。
Gitでのロールバック
ソースコードの変更を記録するGitにおいて、間違ったコミットをしてしまったり、バグを埋め込んでしまったりした際に、過去のコミットの状態にコードを巻き戻すことをロールバックと呼ぶことがある。
代表的な方法には、変更を打ち消す新しいコミットを作る git revert や、ブランチの指すコミットを戻す git reset がある。
デプロイでのロールバック
新バージョンのWebサイトをデプロイした直後、本番環境で予期せぬ致命的なバグが見つかったとする。
この際、すぐにユーザーがアクセスできる状態へ戻すため、一つ前の動いていたバージョンに戻す操作もロールバックと呼ばれる。
AIコーディングとの関係
AIにデータベースの複数テーブルを更新するバックエンドのコードを書かせる場合は、トランザクション処理を明示的に指示する必要がある。
実装では、try-catch文で明示的にロールバックする方法だけでなく、Laravelの DB::transaction() やPrismaの $transaction のように、例外時に自動でロールバックするAPIを使う方法もある。
トランザクションを書かない単純なコードをAIが生成した場合、片方のテーブル更新だけが成功し、もう片方が失敗するデータ不整合が残ってしまう。
AIへ指示する際のポイント
- 「Laravel(PHP)で、ユーザーの決済と注文データの登録を同時に行うコードを書いて。例外(Exception)が発生した場合は必ずデータベースをロールバックするようにして」
- 「Prisma(Node.js ORM)の
$transaction機能を使って、複数のデータ作成処理を安全に実行するサンプルコードを書いて」
よくある勘違い
ロールバックとフォールバックの違いは?
混同しやすいが、対処アプローチが真逆である。
- ロールバック(巻き戻し): エラーが起きたので、処理自体を「なかったことにして元に戻す」。
- フォールバック(代替動作): エラーが起きたが、処理を止めずに「代替手段でなんとか進める」。
送金処理などでデータを守るためには「ロールバック」が必要であり、Webサイトの表示を維持するためには「フォールバック」が役立つ。
ロールバックは何度でも気軽に実行していい?
開発環境ではロールバックを気軽に試せるが、本番環境では慎重な判断が必要である。特に、データベースのマイグレーション(カラム追加・削除など)が伴う場合、ロールバックによってそのカラムに保存済みのデータが消えてしまうリスクがある。
Gitのソースコードロールバックとデータベースのロールバックは別物であり、コードを古いバージョンに戻しても、その間にDBに保存されたデータは残り続ける。コードとデータのバージョンが不一致になることで、新たなバグや不整合が生じるケースもある。
DBのロールバックとGitのロールバックは同じ仕組みで動いている?
どちらも「元に戻す」操作だが、仕組みは大きく異なる。
データベースのロールバックは、ログや未確定変更の管理情報を使い、まだ確定していない変更を反映しない、または取り消す仕組みである。内部実装はデータベース製品によって異なる。
一方、Gitのロールバック(git revert や git reset)は、過去のコミット(スナップショット)を使ってファイルの状態を元に戻す操作であり、データベースのACIDトランザクションとは別物である。また、Gitのロールバックはファイルの状態を変えるだけなので、稼働中のサーバーのデータベースのデータはGitの操作では変わらない点も重要である。
まとめ
- ロールバックは、一連の処理が途中で失敗した際に、すべての変更をキャンセルして実行前の状態に戻すこと。
- データベースの「トランザクション」機能の中心であり、データの不整合を防ぐために不可欠な技術。
- Gitでのソースコードの巻き戻しや、サーバーのバージョンを元に戻す際にも使われる言葉。
- データの整合性が重要なAPIをAIに作らせる際は、トランザクションとロールバックのコードを忘れずに指示しよう。
情報ソース
より詳しくAIに聞いてみよう
- データベースのトランザクションが満たすべき性質「ACID特性(原子性、一貫性、独立性、永続性)」について、初心者向けに解説してください。
- Gitで間違ったコミットをしてしまったとき、
git resetとgit revertのどちらのロールバック手法を使うべきですか?使い分けを教えてください。 - Webアプリのデプロイで、本番環境を旧バージョンにロールバックする際、データベースのマイグレーションデータ(カラム追加など)はどう扱うべきですか?
- データベースのセーブポイント(SAVEPOINT)を使って、トランザクションの途中まで部分的にロールバックする方法を、SQLで例を挙げて教えてください。
- GitHub ActionsやCI/CDパイプラインに「デプロイ失敗時の自動ロールバック」を組み込むためのベストプラクティスを教えてください。