| この記事の要点 |
|
ROLLBACK の基本
ROLLBACK は進行中のトランザクションの変更を全て破棄し、トランザクション開始前の状態に戻すコマンドです。
BEGIN; -- または START TRANSACTION
UPDATE accounts SET balance = balance - 1000 WHERE id = 1;
UPDATE accounts SET balance = balance + 1000 WHERE id = 2;
-- 振込先口座が存在しないと判明
ROLLBACK;
-- → 上の 2 つの UPDATE は無かったことに
-- 正常時は COMMIT
BEGIN;
UPDATE accounts SET balance = balance - 1000 WHERE id = 1;
UPDATE accounts SET balance = balance + 1000 WHERE id = 2;
COMMIT;
AutoCommit と BEGIN
多くの DB はAutoCommit が ON がデフォルトです。1 つの SQL ごとに自動的にコミットされ、ROLLBACK しても何も戻りません。明示的なトランザクションには BEGIN が必要です。
| DB | AutoCommit デフォルト | トランザクション開始 |
|---|---|---|
| MySQL | ON | START TRANSACTION; または BEGIN; |
| PostgreSQL | ON (psql) | BEGIN; |
| Oracle | OFF(明示 COMMIT 必要) | 暗黙的に開始 |
| SQL Server | ON | BEGIN TRANSACTION; |
-- MySQL: AutoCommit を OFF に
SET autocommit = 0;
UPDATE users SET status = 'active' WHERE id = 1;
ROLLBACK; -- 取り消し成功
-- 確認
SELECT status FROM users WHERE id = 1; -- 元のまま
-- 元に戻す
SET autocommit = 1;
SAVEPOINT による部分ロールバック
長いトランザクションで「ここまでは戻したいが先頭までは戻したくない」場合に SAVEPOINT を使います。
BEGIN;
INSERT INTO orders (id, customer_id) VALUES (1, 100);
SAVEPOINT after_order;
INSERT INTO order_items (order_id, sku) VALUES (1, 'A');
INSERT INTO order_items (order_id, sku) VALUES (1, 'B');
SAVEPOINT after_items;
UPDATE inventory SET qty = qty - 1 WHERE sku = 'A';
-- ★ qty が足りずビジネスルール違反と判明
ROLLBACK TO SAVEPOINT after_items;
-- → inventory UPDATE のみ取り消し。orders / order_items は残る
-- ここから別の在庫処理を試す
UPDATE inventory SET qty = qty - 1 WHERE sku = 'C';
COMMIT;
暗黙コミット (DDL)
多くの DB では DDL (CREATE / ALTER / DROP) が暗黙的にコミットを発生させます。トランザクション内で DDL を実行するとそこまでが確定し、後から ROLLBACK しても戻りません。
-- MySQL の例
BEGIN;
INSERT INTO users (name) VALUES ('Alice');
CREATE TABLE logs (id INT); -- ★ ここで暗黙 COMMIT
INSERT INTO logs (id) VALUES (1);
ROLLBACK;
-- → logs テーブルは残る、INSERT (Alice) も残る、INSERT (1) のみ取り消し
-- ※ MySQL は DDL の Atomic 性が 8.0 で改善されたが、トランザクション境界は変わる
-- PostgreSQL は DDL もトランザクション可能
BEGIN;
CREATE TABLE logs (id INT);
ROLLBACK;
-- → logs テーブルは作られていない(PG の強み)
PostgreSQL は例外的に DDL もロールバック可能です。スキーママイグレーション運用で重宝されます。
Spring @Transactional でのロールバック
@Service
public class OrderService {
@Transactional(rollbackFor = Exception.class)
public void placeOrder(Order order) {
orderRepo.save(order);
inventoryService.reserve(order); // ★ ここで例外が出ると...
paymentService.charge(order);
// → save も reserve も両方ロールバック
}
}
// rollbackFor 指定の理由:
// デフォルトでは RuntimeException / Error のみロールバック対象
// checked Exception (IOException 等) はコミットされる
// → rollbackFor = Exception.class で全例外を対象に
// 部分ロールバックには Propagation.REQUIRES_NEW でサブトランザクション化
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void logFailure(String msg) { ... }
// アノテーション以外で明示ロールバック
TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
Laravel でのロールバック
use Illuminate\Support\Facades\DB;
// パターン1: try / catch + 手動制御
DB::beginTransaction();
try {
$order = Order::create([...]);
OrderItem::insert([...]);
DB::commit();
} catch (\Throwable $e) {
DB::rollBack();
throw $e;
}
// パターン2: クロージャ(推奨)
// 例外が出れば自動で rollBack、正常終了で commit
DB::transaction(function () {
$order = Order::create([...]);
OrderItem::insert([...]);
}, 3); // ★ デッドロック時 3 回リトライ
// 手動 SAVEPOINT 風: ネスト transaction
DB::transaction(function () {
DB::table('outer')->insert(['v' => 1]);
try {
DB::transaction(function () {
DB::table('inner')->insert(['v' => 2]);
throw new \Exception('rollback inner');
});
} catch (\Throwable $e) {
// inner だけ rollBack。outer はそのまま COMMIT
}
});
Nested Transaction (ネストトランザクション)
多くの DB は本物のネストトランザクションを持たず、内側はSAVEPOINT で代用されます。Laravel / Spring もそうです。
BEGIN; <- レベル 1
... 処理 ...
SAVEPOINT sp1; <- レベル 2 開始(ネスト風)
... 処理 ...
SAVEPOINT sp2; <- レベル 3
... 処理 ...
RELEASE SAVEPOINT sp2;
RELEASE SAVEPOINT sp1;
COMMIT;
* RELEASE SAVEPOINT は「成功確定」
* ROLLBACK TO SAVEPOINT で個別取消
* 最終的に外側で COMMIT しない限り全て一括コミット
Distributed Transaction (XA)
複数の DB / リソースを跨ぐ場合は XA (X/Open Distributed Transaction Processing) や 2 相コミットを使います。
2 相コミット (2PC):
Phase 1 (Prepare): すべての参加 RM に「準備できる?」と聞く
全員 OK → Phase 2 へ。1 つでも NG → 全員 ROLLBACK
Phase 2 (Commit) : 全員 COMMIT
どこかで通信障害 → タイムアウトで ROLLBACK
実装:
- JTA (Java Transaction API) / Atomikos / Bitronix
- MySQL XA: XA START 'gtrid'; XA END 'gtrid'; XA PREPARE 'gtrid'; XA COMMIT 'gtrid';
- マイクロサービスでは XA を避け、Saga パターンが主流
ROLLBACK が効かないケース
- AutoCommit ON のまま単発 SQL を流した → そもそもトランザクションが無い
- DDL を挟んだ → 暗黙コミットでそこまで確定
- テーブルが非トランザクションエンジン (MySQL MyISAM 等) → 全て無効
- 外部リソース (ファイル / API 呼び出し / メール送信) → DB の ROLLBACK は影響しない
- セッションが切れて Connection が閉じた → サーバ側で自動 ROLLBACK 済み
FAQ
Q: TRUNCATE はロールバックできる?
A: PostgreSQL は可能、MySQL / Oracle は不可(DDL 扱いで暗黙コミット)。大量削除なら DELETE + LIMIT バッチ + COMMIT が安全。
Q: ストアドプロシージャ内の ROLLBACK は外側のトランザクションも巻き戻す?
A: DB によります。SQL Server / Oracle は全体を巻き戻す。MySQL は DECLARE HANDLER で挙動を制御。
Q: ROLLBACK しても物理ディスクは戻る?
A: 戻ったように見えますが、内部的には UNDO ログを使った論理復元です。物理ページは断片化が残ることもあり、長期運用では VACUUM / OPTIMIZE TABLE が必要。
子ページはありません
- COMMIT (トランザクション制御)
- ROLLBACK
- SAVEPOINT
人気ページ
- 1 Eclipseで「サーバーに追加または除去できるリソースがありません。」の原因と対処法
- 2 tomcat の起動 / 停止ログと catalina.log・catalina.out の違い
- 3 JavaScript で base URL を取得する方法|window.location.origin
- 4 YouTube Data API v3 エラー一覧|403・400・404 の原因と対処
- 5 Laravel エラー一覧|500/Blade/DB 接続/ルーティングの代表エラー
- 6 3Dグラフィックスとは|モデリング/レンダリング/主要ソフトウェア (Blender / Maya)
- 7 Spring Frameworkのアノテーション一覧
- 8 【Spring】@Valueアノテーションとは
- 9 CATALINA_HOME の確認方法 (Linux / Mac)
- 10 【Spring】@Autowiredアノテーションとは
最近更新/作成されたページ
- MariaDB Monitor (mysql コマンド) の使い方 2026-10-14 15:21:02
- MariaDB の管理ツール (phpMyAdmin / DBeaver 等) 2026-10-14 15:21:02
- Google Custom Search JSON API|新規受付終了・移行期限と既存実装の確認 2026-10-14 14:50:13
- MySQL rootの初期パスワード確認|導入方式・Docker既存DB・復旧の注意 2026-10-14 14:39:34
- MySQL root パスワードの変更方法(ALTER USER / mysqladmin / パスワード忘れ時の復旧) 2026-10-14 14:39:34
- MySQL ALTER USER の使い方|パスワード変更・アカウントロック 2026-10-14 14:39:34
- MySQL ERROR 1129|ホスト遮断の原因・カウンタ・解除前の確認 2026-10-14 14:04:49
- MySQL ERROR 1820・1862|期限切れパスワードの安全な更新と確認 2026-10-14 14:04:49
- MySQL ERROR 1698|ソケット認証・OSユーザー・接続経路の確認 2026-10-14 14:04:49
- mysql_configが見つからない|mysqlclientの旧ビルドとpkg-configの確認 2026-10-14 13:36:32
- MySQLエラー一覧|番号・SQLSTATE別の原因と安全な確認手順 2026-10-14 13:36:32
- インストール直後にNetbeansが反応しない 2026-10-14 13:07:02
- NetBeans でよくあるエラー一覧と対処法 — JDK / Tomcat / PHP / メモリ不足 2026-10-14 13:07:02
- Apache NetBeans入門|起動JDK・プロジェクト作成・関連手順 2026-10-14 13:07:02
- 【Laravel】ページング(ページネーション)をする方法 2026-10-14 12:31:44