トランザクション・ロールバックとは、データベースにおけるトランザクション(一連の処理単位)の実行中にエラーや障害が発生した際に、そのトランザクションで行われたすべての変更を取り消して処理開始前の状態に戻す操作です。
銀行の送金処理を例にすると、「口座Aから引き落とす」と「口座Bへ入金する」という2つの操作がひとつのトランザクションを構成しており、どちらかが失敗した場合にロールバックが実行されることでデータの不整合を防ぎます。
データベースの整合性と信頼性を保つための根本的な仕組みであり、ACID特性のうちの「原子性(Atomicity)」を実現する中核的なメカニズムです。
本記事では、トランザクション・ロールバックとは何か、意味や仕組み、データベース・コミット・ACID特性・障害復旧・原子性などについてわかりやすく解説していきます。
データベースの基礎を学んでいる方から、より深くトランザクション管理を理解したいエンジニアの方まで、役立つ内容をお届けします。
トランザクション・ロールバックはACID特性の原子性を実現するデータ整合性保護の仕組み
それではまず、トランザクションとロールバックの基本概念、そしてACID特性との関係について解説していきます。
トランザクション(Transaction)とは、「すべて成功するか、すべて失敗するか」のどちらかしかない処理の最小単位であり、複数のデータベース操作をひとまとまりとして扱うことでデータの整合性を保証する概念です。
ロールバック(Rollback)はトランザクションの失敗時に実行される「巻き戻し」操作であり、コミット(Commit)はトランザクションの成功時に変更を永続化する操作です。
この2つの操作によって、トランザクションは「完全に完了するか完全に取り消されるか」のどちらかが保証されます。
ACID特性の4つの要素:原子性(Atomicity)・一貫性(Consistency)・分離性(Isolation)・耐久性(Durability)。ロールバックは主に「原子性」の実現を担いますが、一貫性の維持にも直接貢献しています。ACID特性はリレーショナルデータベースの信頼性の根幹です。
ACID特性の詳細とロールバックの関係
ACID特性の4つの要素それぞれの意味を整理します。
原子性(Atomicity)は「トランザクション内のすべての操作が完全に実行されるか、まったく実行されないかのどちらか」という性質です。ロールバックはこの原子性を実現する直接的なメカニズムです。
一貫性(Consistency)は「トランザクションの前後でデータベースが定義したすべての整合性制約を満たす状態を維持する」という性質です。ロールバックによって不整合な中間状態が永続化されることを防ぎます。
分離性(Isolation)は「同時に実行される複数のトランザクションが互いに影響を与えない」という性質です。分離性のレベルはトランザクション分離レベルで調整されます。
耐久性(Durability)は「コミットされたトランザクションの結果は障害が発生しても失われない」という性質です。WALログなどの仕組みによって実現されます。
ロールバックの内部的な仕組み(UNDOログ)
データベースがロールバックを実現するための中心的な仕組みが「UNDOログ(アンドゥログ)」です。
UNDOログとは、トランザクションが行った各変更操作の「元に戻すための情報」を記録したログです。
トランザクションが「行AのカラムXを100から200に変更した」場合、UNDOログには「行AのカラムXを200から100に戻す」という逆の操作が記録されます。
ロールバックが実行されると、このUNDOログを逆順に適用することですべての変更が取り消されます。
UNDOログの動作イメージ:
操作1:INSERT INTO accounts (id, balance) VALUES (1, 1000);
→ UNDOログ: DELETE FROM accounts WHERE id = 1;
操作2:UPDATE accounts SET balance = 500 WHERE id = 1;
→ UNDOログ: UPDATE accounts SET balance = 1000 WHERE id = 1;
ロールバック時:UNDOログを逆順(操作2→1の逆)に適用してすべて取り消す
MySQLのInnoDBエンジンではUNDOログはtablespaceに保存されており、ロールバックだけでなくMVCC(マルチバージョン同時実行制御)にも使用されています。
コミットとロールバックのSQL構文
標準SQLにおけるトランザクション制御のコマンドは以下の通りです。
トランザクションの開始:
BEGIN; (またはSTART TRANSACTION;)
処理の実行:
UPDATE accounts SET balance = balance – 10000 WHERE account_id = ‘A’;
UPDATE accounts SET balance = balance + 10000 WHERE account_id = ‘B’;
成功時:変更を確定
COMMIT;
失敗時:変更をすべて取り消す
ROLLBACK;
多くのプログラミング言語のDBライブラリでは、try-catch構文と組み合わせてエラー発生時に自動的にROLLBACKが実行されるよう実装するのが一般的なパターンです。
セーブポイントと部分ロールバック
続いては、トランザクションの一部だけを取り消せる「セーブポイント」と部分ロールバックの仕組みを確認していきます。
大規模なトランザクションでは、すべての変更を取り消すのではなく特定の中間点まで戻りたい場合があります。
SAVEPOINTの使い方
SAVEPOINTはトランザクション内に「ここまでの処理は保持したい」という中間チェックポイントを設ける機能です。
SAVEPOINTの使用例:
BEGIN;
INSERT INTO orders (order_id, customer_id) VALUES (1, 100);
SAVEPOINT after_order;
INSERT INTO order_items (order_id, product_id, qty) VALUES (1, ‘P001’, 2);
— この処理が失敗した場合
ROLLBACK TO SAVEPOINT after_order;
— after_order以降の変更だけが取り消される
— ordersテーブルへのINSERTは保持される
COMMIT;
SAVEPOINTを活用することで、長いトランザクションの一部だけを取り消しながら残りの処理を継続するという柔軟なエラーハンドリングが可能になります。
Oracle・PostgreSQL・MySQLなど主要なRDBMSで標準的にサポートされています。
自動コミット(Auto Commit)とロールバックの関係
多くのデータベースクライアントではデフォルトで「自動コミット(Auto Commit)」が有効になっており、BEGINを明示しない単一のSQL文は自動的にコミットされます。
自動コミットが有効な状態でUPDATEやDELETEを実行すると、明示的なROLLBACKで取り消すことはできません。
大量データの削除・更新を行う前には必ず明示的にBEGIN;でトランザクションを開始し、実行結果を確認してからCOMMITする習慣が重要です。この習慣がデータの誤削除・誤更新の防止に直結します。
障害時の自動ロールバック
サーバークラッシュや接続切断などの障害が発生した場合、データベースは次回起動時にクラッシュリカバリを実行します。
クラッシュリカバリでは、コミットされていないトランザクションの変更はUNDOログを使って自動的にロールバックされます。
一方、コミット済みのトランザクションはREDOログを使って確実に再適用されます。
このWAL(Write-Ahead Logging)メカニズムがACID特性の耐久性(Durability)を実現する基盤となっています。
実装パターンとロールバックのベストプラクティス
続いては、アプリケーションコードでロールバックを適切に実装するための具体的なパターンとベストプラクティスを確認していきます。
正しいトランザクション管理はデータの整合性を守るうえで最も重要な実装の責任のひとつです。
Javaでのトランザクション・ロールバック実装
Java(JDBC)でのトランザクション管理の標準的なパターンは以下の通りです。
Connection conn = dataSource.getConnection();
try {
conn.setAutoCommit(false); // 自動コミット無効化
// DB操作
stmt.executeUpdate(“UPDATE accounts SET balance = balance – 10000 WHERE id = 1”);
stmt.executeUpdate(“UPDATE accounts SET balance = balance + 10000 WHERE id = 2”);
conn.commit(); // 成功時はコミット
} catch (SQLException e) {
conn.rollback(); // 例外発生時はロールバック
throw e;
} finally {
conn.setAutoCommit(true);
conn.close();
}
Spring Frameworkでの@Transactionalアノテーション
Spring Frameworkでは@Transactionalアノテーションを使うことで、宣言的なトランザクション管理が実現できます。
@Service
public class TransferService {
@Transactional // このメソッド全体がひとつのトランザクション
public void transfer(String fromId, String toId, int amount) {
accountRepository.decreaseBalance(fromId, amount);
accountRepository.increaseBalance(toId, amount);
// 例外が発生すると自動的にROLLBACKされる
}
}
@Transactionalアノテーションはデフォルトで非検査例外(RuntimeException)発生時に自動ロールバックします。
検査例外でもロールバックしたい場合は「@Transactional(rollbackFor = Exception.class)」のように指定します。
まとめ
本記事では、トランザクション・ロールバックとは何か、意味や仕組み、データベース・コミット・ACID特性・障害復旧・原子性などについて解説しました。
ロールバックはACID特性の原子性を実現するためのデータ整合性保護の中核的な仕組みであり、UNDOログによる変更の取り消しとWALによる障害復旧がその技術的基盤です。
SAVEPOINTによる部分ロールバック・自動コミットの適切な制御・Spring@Transactionalなどの宣言的トランザクション管理を正しく活用することで、信頼性の高いデータベースアプリケーションが実現できます。
トランザクション管理は「データの命を守る」最も重要な実装の責任のひとつとして、すべてのデータベース開発者が深く理解すべき分野でしょう。