データベース操作を学ぶうえで、「コミット」と「ロールバック」は避けて通れない重要な概念です。
「コミットは確定、ロールバックは取り消し」と覚えている方は多いかもしれませんが、それぞれの仕組み・使い方・整合性への影響・障害復旧での役割まで理解している方は意外と少ないのではないでしょうか。
本記事では、トランザクションのコミットとロールバックについて、意味・違い・具体的な使い方・整合性への影響・障害復旧まで、わかりやすく解説していきます。
コミットとロールバックとは?トランザクションの2つの結末
それではまず、コミットとロールバックの基本的な意味と役割について解説していきます。
トランザクションは必ず「コミット」か「ロールバック」のいずれかで終わります。
この2つは、トランザクションの「成功の結末」と「失敗の結末」を表します。
コミットとロールバックの基本定義
コミット(COMMIT):トランザクション内のすべての操作を「確定」し、データベースに永続的に反映させることです。コミット後はロールバックできません。
ロールバック(ROLLBACK):トランザクション内のすべての操作を「取り消し」、トランザクション開始前の状態に戻すことです。エラー発生時や明示的な取り消し指示によって実行されます。
コミットは「保存ボタンを押す」イメージ、ロールバックは「全部取り消してやり直す」イメージで捉えるとわかりやすいでしょう。
ただし、コンピューターの「元に戻す(Ctrl+Z)」とは異なり、コミット後は原則として取り消せません。
また、コミット前の変更は基本的にそのトランザクションの中だけで見えており、他のユーザーからは見えていません(分離レベルによって異なります)。
コミットとロールバックのSQLによる操作
SQLを使った具体的なコミット・ロールバックの操作を見てみましょう。
【コミットの例(MySQL/PostgreSQL)】
START TRANSACTION;
UPDATE accounts SET balance = balance – 5000 WHERE user_id = 1;
UPDATE accounts SET balance = balance + 5000 WHERE user_id = 2;
COMMIT; ← 両方の更新を確定・永続化
【ロールバックの例(エラー発生時)】
START TRANSACTION;
UPDATE accounts SET balance = balance – 5000 WHERE user_id = 1;
— ここでエラー発生(例:制約違反)
ROLLBACK; ← 最初のUPDATEも含めてすべて取り消し
ロールバックを実行することで、トランザクション開始時点の状態に完全に戻ります。
このロールバックの能力こそが、原子性(Atomicity)を実現する核心的な仕組みです。
オートコミットとは何か
多くのデータベースでは「オートコミット(AutoCommit)」という設定が存在します。
オートコミットが有効な場合、各SQL文が実行されるたびに自動的にコミットが行われます。
MySQLのデフォルトはオートコミットONです。
オートコミットが有効な状態では、明示的なトランザクション管理(BEGIN〜COMMIT/ROLLBACK)を行わないと、1つのSQL文が即座にコミットされてしまい、ロールバックができなくなります。
複数のSQL文をひとつのトランザクションとして扱いたい場合は、必ずSTART TRANSACTIONで明示的にトランザクションを開始することが重要です。
コミットとロールバックの違いを詳しく比較
続いては、コミットとロールバックの違いをより詳しく確認していきます。
コミットとロールバックの違い一覧
| 比較項目 | コミット(COMMIT) | ロールバック(ROLLBACK) |
|---|---|---|
| 意味 | 処理を確定・永続化する | 処理を取り消して元に戻す |
| 実行タイミング | すべての処理が成功した後 | エラー発生時や明示的な取り消し時 |
| データへの影響 | 変更がデータベースに反映される | 変更がすべて元に戻る |
| 可逆性 | 原則として取り消し不可 | 実行前の状態に戻る |
| ロックの解放 | トランザクションが保持するロックを解放 | 同上 |
| ログへの影響 | 変更がWALに永続的に記録される | 変更ログが無効化される |
コミットもロールバックも、実行後はトランザクションが終了し、保持していたロック(排他制御)が解放されます。
ロックの解放はデータベースの並行処理性能に直接影響するため、トランザクションはできるだけ短時間で完了させることが設計上の鉄則です。
セーブポイントとは何か
トランザクションの途中で「ここまでの処理は保持しながら、一部だけ取り消したい」という場合に使えるのが「セーブポイント(SAVEPOINT)」です。
【セーブポイントの使用例】
START TRANSACTION;
INSERT INTO orders … ← 注文登録
SAVEPOINT order_saved; ← セーブポイント設定
INSERT INTO payments … ← 決済登録
— 決済でエラー発生
ROLLBACK TO SAVEPOINT order_saved; ← 決済だけ取り消し、注文は保持
COMMIT; ← 注文だけ確定
セーブポイントは、長大なトランザクションの中で段階的な処理を行う際に非常に便利な機能です。
特に、処理の一部が失敗してもその前の処理を活かしたい場合に、細かい制御ができるのがセーブポイントの大きな強みです。
データの整合性とロールバックの関係
続いては、ロールバックがデータの整合性をどのように守るかについて確認していきます。
整合性を守るためのロールバックの役割
データの整合性(Consistency)を守るためには、途中で失敗した処理を「なかったこと」にするロールバックが不可欠です。
例えば、ECサイトの注文処理を考えてみましょう。
【注文処理のトランザクション例】
操作1:在庫数を1減らす
操作2:注文レコードを作成する
操作3:顧客のポイントを加算する
操作4:決済処理を実行する
→ 操作4の決済失敗時:操作1〜3もROLLBACKで取り消し
→ 整合性が保たれる(在庫は減らず、注文も作成されない)
ロールバックがなければ、「在庫は減ったのに注文は作成されていない」「注文はあるのに決済は完了していない」などの矛盾したデータが残ってしまいます。
ロールバックはデータの整合性を「オールオアナッシング」で保証する、トランザクション管理の最も重要な安全機能です。
アプリケーション層でのトランザクション管理
現代のWebアプリケーション開発では、データベース操作をアプリケーションコードから行うことがほとんどです。
Javaのフレームワーク(Spring)やPythonのORM(SQLAlchemy)、Ruby on Railsなどでは、トランザクションの管理をアプリケーション層でコントロールする仕組みが提供されています。
例えば、Pythonのコードでは「with db.transaction():」のような構文でトランザクションを管理し、例外が発生した場合は自動的にロールバックが実行される設計が一般的です。
アプリケーション層でのトランザクション管理のポイントは、例外処理とロールバックを必ずセットで設計することです。
障害復旧におけるロールバックとコミットの役割
続いては、システム障害が発生した場合にコミットとロールバックがどのように機能するかについて確認していきます。
WAL(先行書き込みログ)による障害からの復旧
データベースシステムが障害から復旧する際、WAL(Write-Ahead Logging:先行書き込みログ)と呼ばれるログファイルが重要な役割を果たします。
WALはデータへの変更をディスクに書き込む前に、まずログファイルに記録する仕組みです。
システムが突然クラッシュした場合、再起動時にWALを参照してリカバリーが行われます。
【障害復旧時のリカバリー処理】
ケース1:コミット済みのトランザクションがデータに反映されていない場合
→ REDOログを使って変更を再適用する(ロールフォワード)
ケース2:未コミットのトランザクションが途中で残っている場合
→ UNDOログを使って変更を取り消す(ロールバック)
このリカバリー処理が自動的に行われることで、障害後も「コミット済みのデータは必ず保存される・未コミットのデータは必ず取り消される」という保証が維持されます。
これがACID特性の「D:耐久性」を支える仕組みです。
バックアップとポイントインタイムリカバリー
より大規模な障害(ハードウェア故障・データ削除など)に対応するために、データベースのバックアップと「ポイントインタイムリカバリー(PITR)」が活用されます。
PITRとは、バックアップとWALを組み合わせて、特定の時点の状態にデータベースを復元する技術です。
例えば、「午前10時にデータベースのバックアップを取得し、午後2時に誤ってテーブルを削除してしまった」場合、PITRを使うことで午後1時59分時点の状態に復元することが可能です。
PITRはAmazon RDSやGoogle Cloud SQLなどのクラウドデータベースサービスでも標準機能として提供されており、企業の重要データを守るための必須の仕組みとなっています。
まとめ
本記事では、トランザクションのコミットとロールバックの意味・違い・整合性への影響・障害復旧での役割について詳しく解説しました。
コミットはトランザクションの処理を確定・永続化する操作であり、ロールバックはすべての処理を取り消して元の状態に戻す操作です。
セーブポイントを使うことで、部分的なロールバックも可能になります。
ロールバックはデータの整合性を守るための根幹的な仕組みであり、WALと組み合わせることで障害発生時の自動復旧にも活用されます。
コミットとロールバックを正しく理解・活用することが、信頼性の高いデータベースシステムを構築するための第一歩です。
本記事を参考に、トランザクション管理の理解をさらに深めていきましょう。