SQLのROLLBACKとは?トランザクション制御の基本と実例で完全理解

データベース・SQL

データベースを扱っていて、こんな経験はありませんか?

  • 「間違ってUPDATEしてしまった…」
  • 「途中でエラーが出て、処理が中途半端になった…」
  • 「複数のテーブルを一度に更新したいけど、失敗したら全部元に戻したい」

そんなときに役立つのがROLLBACK(ロールバック)です。

データベースを扱う上で避けて通れないのが「トランザクション制御」です。

ROLLBACKは、データの変更を安全に取り消すために使う重要な機能です。

この記事では、SQLのROLLBACKの意味、使い方、COMMITとの関係、実務での注意点などを、初学者でも理解しやすい形で解説します。

スポンサーリンク

ROLLBACKとは?

簡単に言うと

ROLLBACKは、SQLのトランザクション制御文のひとつで、未確定の変更(INSERT・UPDATE・DELETEなど)をキャンセルして元の状態に戻すために使います。

身近な例で考えてみよう

ROLLBACKは「操作の取り消し(Ctrl+Z)」のようなものです。

  • Word文書:間違って文字を削除 → Ctrl+Zで元に戻す
  • データベース:間違ってデータを削除 → ROLLBACKで元に戻す

基本的な構文

ROLLBACK;

たったこれだけで、トランザクション内で行った変更をすべて取り消せます。

ROLLBACKが使われる場面

場面ROLLBACKの効果
操作ミス間違ったデータを更新更新前の状態に戻す
エラー発生途中で処理が失敗処理開始前の状態に戻す
テスト実行データ変更のテストテスト前の状態に戻す
バッチ処理大量処理の途中で問題発生処理開始前の状態に戻す

トランザクションとCOMMITの関係

トランザクションって何?

トランザクションとは、ひとまとまりの処理単位のことです。

「全て成功するか、全て失敗するか」が原則で、これを原子性といいます。

銀行振込の例で理解しよう

振込処理 = 1つのトランザクション
1. A口座から10,000円を引く
2. B口座に10,000円を入れる

もし途中で失敗したら:

  • ❌ A口座だけお金が減る → 困る!
  • ⭕ 全部なかったことにする(ROLLBACK) → 安全!

基本的なトランザクション制御

コマンド役割タイミング
BEGIN または START TRANSACTIONトランザクション開始処理の最初
COMMIT変更を確定(保存)すべて成功した時
ROLLBACK変更を破棄(取り消し)問題が発生した時

実例:銀行振込のSQL

-- トランザクション開始
BEGIN;

-- A口座から10,000円を引く
UPDATE accounts SET balance = balance - 10000 WHERE account_id = 'A001';

-- B口座に10,000円を入れる
UPDATE accounts SET balance = balance + 10000 WHERE account_id = 'B001';

-- 成功の場合:変更を確定
COMMIT;

-- 失敗の場合:変更を取り消し
-- ROLLBACK;

処理の流れ

1. BEGIN → トランザクション開始
2. UPDATE → データ変更(仮の状態)
3. UPDATE → データ変更(仮の状態)
4. COMMIT → 変更を正式に保存
   または
   ROLLBACK → すべての変更を取り消し

ROLLBACKの実践的な使い方

使いどころ1:バッチ処理でのエラー対応

BEGIN;

-- 大量のデータを処理
UPDATE products SET price = price * 1.1; -- 価格を10%アップ

-- 処理件数を確認
SELECT COUNT(*) FROM products WHERE updated_at > NOW() - INTERVAL 1 MINUTE;

-- 予想と違う場合は取り消し
-- ROLLBACK;

-- 問題なければ確定
-- COMMIT;

使いどころ2:データ移行での安全確認

BEGIN;

-- 古いテーブルから新しいテーブルにデータをコピー
INSERT INTO new_customers 
SELECT customer_id, name, email FROM old_customers;

-- データ件数を確認
SELECT 
    (SELECT COUNT(*) FROM old_customers) AS old_count,
    (SELECT COUNT(*) FROM new_customers) AS new_count;

-- 件数が一致すればCOMMIT、そうでなければROLLBACK

使いどころ3:テスト環境でのデータ確認

BEGIN;

-- テスト用にデータを変更
UPDATE users SET status = 'premium' WHERE user_id = 123;

-- 結果を確認
SELECT * FROM users WHERE user_id = 123;
SELECT * FROM user_benefits WHERE user_id = 123;

-- テスト完了後、必ず元に戻す
ROLLBACK;

重要な注意点

1. COMMITした後はROLLBACKできない

BEGIN;
UPDATE users SET name = '新しい名前' WHERE id = 1;
COMMIT; -- ここで確定される

ROLLBACK; -- ❌ これは効果なし!

2. 自動コミットに注意

データベースデフォルト設定対策
MySQL自動コミット = ONSTART TRANSACTIONを使う
PostgreSQL自動コミット = OFFそのまま使える
SQLite自動コミット = ONBEGINを使う

MySQLでの正しい使い方

-- 自動コミットを無効にする方法1
START TRANSACTION;
UPDATE users SET name = 'test';
ROLLBACK;

-- 自動コミットを無効にする方法2
SET autocommit = 0;
UPDATE users SET name = 'test';
ROLLBACK;

3. DDL(データ定義言語)の扱い

操作ROLLBACKできる?
INSERT, UPDATE, DELETE⭕ できるデータの変更
CREATE TABLE△ データベース依存テーブル作成
DROP TABLE△ データベース依存テーブル削除
ALTER TABLE△ データベース依存テーブル構造変更

データベースごとのROLLBACK対応状況

主要データベースの比較

データベースROLLBACK対応DDLのトランザクション特徴
PostgreSQL⭕ 完全対応⭕ DDLもトランザクション可最も安全
MySQL⭕ InnoDBのみ❌ 一部DDLは自動コミットストレージエンジンに注意
SQLite⭕ 対応△ 制限あり軽量だが機能制限
Oracle⭕ 完全対応⭕ 基本的に対応エンタープライズ級
SQL Server⭕ 完全対応⭕ 対応Windows環境に最適

MySQL利用時の重要な注意点

InnoDBを使う

-- テーブル作成時にInnoDBを指定
CREATE TABLE users (
    id INT PRIMARY KEY,
    name VARCHAR(100)
) ENGINE=InnoDB;

-- 現在のストレージエンジンを確認
SHOW TABLE STATUS WHERE Name = 'users';

実務での活用パターン

パターン1:プログラムでのエラーハンドリング

-- Python(擬似コード)の例
try:
    cursor.execute("BEGIN;")
    cursor.execute("UPDATE accounts SET balance = balance - 100 WHERE id = 1;")
    cursor.execute("UPDATE accounts SET balance = balance + 100 WHERE id = 2;")
    
    # 残高チェック
    cursor.execute("SELECT balance FROM accounts WHERE id = 1;")
    if cursor.fetchone()[0] < 0:
        raise Exception("残高不足")
    
    cursor.execute("COMMIT;")
except Exception as e:
    cursor.execute("ROLLBACK;")
    print(f"エラーが発生しました: {e}")

パターン2:手動での安全確認

-- 手順1:トランザクション開始
BEGIN;

-- 手順2:変更実行
UPDATE products SET price = price * 0.9 WHERE category = 'electronics';

-- 手順3:結果確認
SELECT category, COUNT(*), AVG(price) FROM products 
WHERE category = 'electronics' 
GROUP BY category;

-- 手順4:問題なければCOMMIT、問題があればROLLBACK
-- COMMIT; または ROLLBACK;

パターン3:複雑な処理の段階的確認

BEGIN;

-- ステップ1:マスターデータ更新
UPDATE categories SET tax_rate = 0.10 WHERE type = 'food';
SELECT COUNT(*) as updated_categories FROM categories WHERE tax_rate = 0.10;

-- ステップ2:商品価格の再計算
UPDATE products p 
JOIN categories c ON p.category_id = c.id 
SET p.final_price = p.base_price * (1 + c.tax_rate)
WHERE c.type = 'food';

-- ステップ3:結果確認
SELECT 
    COUNT(*) as total_products,
    AVG(final_price) as avg_final_price
FROM products p 
JOIN categories c ON p.category_id = c.id 
WHERE c.type = 'food';

-- 問題なければCOMMIT
COMMIT;

よくある間違いと対策

間違い1:トランザクションを開始し忘れ

-- ❌ 悪い例
UPDATE users SET status = 'inactive';
ROLLBACK; -- 効果なし(自動コミットされている)

-- ⭕ 良い例
BEGIN;
UPDATE users SET status = 'inactive';
ROLLBACK; -- 正しく取り消される

間違い2:COMMITとROLLBACKの両方を実行

-- ❌ 悪い例
BEGIN;
UPDATE users SET name = 'test';
COMMIT;
ROLLBACK; -- 意味がない

-- ⭕ 良い例
BEGIN;
UPDATE users SET name = 'test';
-- 条件に応じてどちらか一つだけ実行
-- COMMIT; または ROLLBACK;

間違い3:長時間のトランザクション

-- ❌ 悪い例(長時間ロックが続く)
BEGIN;
UPDATE large_table SET status = 'processing'; -- 100万件
-- 30分かかる重い処理...
COMMIT;

-- ⭕ 良い例(バッチに分割)
-- 1万件ずつ処理して、こまめにCOMMIT

まとめ:ROLLBACKで安全なデータベース操作を

重要なポイント

  • ROLLBACKはトランザクション内の変更を取り消す重要な機能
  • COMMITとの組み合わせでデータの整合性を保つ
  • データベースごとに対応状況が異なるので事前確認が必要
  • 自動コミット設定に注意して使う

安全な操作の流れ

  1. BEGINでトランザクション開始
  2. データ変更の実行
  3. 結果確認(件数、内容など)
  4. 判断:問題なければCOMMIT、問題があればROLLBACK

覚えておきたいベストプラクティス

場面対応
重要なデータ変更必ずトランザクションを使う
バッチ処理エラーハンドリングでROLLBACK
テスト実行必ずROLLBACKで元に戻す
本番環境事前にテスト環境で動作確認

コメント

タイトルとURLをコピーしました