【PL/SQL】コミットとロールバックの正しい使い方

【PL/SQL】コミットとロールバックの正しい使い方 PL/SQL

トランザクション制御はPL/SQLの信頼性と性能に直結します。COMMITとROLLBACKはデータベースの一貫性を保ちつつ、いつ確定・取り消しを行うかを決める重要な操作です。誤用すると整合性崩壊やパフォーマンス劣化を招くため、基本的な仕組みと正しい設計指針を理解しておく必要があります。

トランザクションの基本

Oracleのトランザクションは最初のDML(INSERT/UPDATE/DELETE/MERGE)文で開始され、明示的にCOMMITまたはROLLBACKするまで続きます。SELECTだけではトランザクションは開始されません。セッション終了時は暗黙的にCOMMITが行われるため、テスト環境では意図せずデータが確定してしまうことがあります。

COMMITの役割

COMMITは現在のトランザクションを確定し、変更を永続化します。UNDO情報は破棄され、他セッションから更新結果が見えるようになります。

BEGIN
  UPDATE employees SET salary = salary * 1.1 WHERE deptno = 10;
  COMMIT; -- この時点で確定
END;
/

複数のDMLを1つの論理単位でまとめたいときは、最後に1回だけCOMMITします。処理途中で頻繁にCOMMITするとI/Oコストが増え、パフォーマンスが低下することがあります。

ROLLBACKの役割

ROLLBACKは未確定の変更を取り消し、トランザクション開始時点の状態に戻します。

BEGIN
  INSERT INTO audit_log VALUES(100,'test');
  ROLLBACK; -- 挿入は取り消される
END;
/

部分的に取り消したい場合はSAVEPOINTを使います。

BEGIN
  SAVEPOINT sp1;
  UPDATE employees SET salary = salary * 1.05 WHERE deptno = 20;
  -- 条件によっては戻す
  ROLLBACK TO sp1;
  COMMIT;
END;
/

暗黙のコミットに注意

DDL(CREATE/ALTER/DROP)は実行前後で暗黙のCOMMITを発生させます。これにより他のDMLも強制的に確定してしまうため、トランザクション中にDDLを混在させるのは避けるべきです。

例外処理とロールバック

例外が発生したときは明示的にROLLBACKするか、アプリケーション側で再試行戦略を決めます。WHEN OTHERSで握り潰すのはNGで、ログ出力と適切なロールバックを組み合わせるのが基本です。

BEGIN
  UPDATE accounts SET balance = balance - 100 WHERE id = 1;
  UPDATE accounts SET balance = balance + 100 WHERE id = 2;
  COMMIT;
EXCEPTION
  WHEN OTHERS THEN
    ROLLBACK; -- 整合性を保つ
    RAISE;    -- 呼び出し側に再通知
END;
/

パフォーマンスの観点

コミット頻度が高すぎるとLGWRによるREDO書き込みが増え、性能劣化やログ肥大化を招きます。逆に遅すぎるとUNDOが膨張し、長時間ロールバック時に負荷がかかります。目安として数千件~数万件単位のバッチごとにまとめてCOMMITするのが一般的です。

ベストプラクティス

1. DMLを1つの論理単位でまとめてCOMMITする
2. 例外発生時はROLLBACKで整合性を保証する
3. DDLとDMLを同一トランザクションに混在させない
4. SAVEPOINTで部分的な取り消しを設計する
5. コミット頻度はパフォーマンスとリカバリ時間のバランスで決める
6. アプリ層との責任分界(誰がCOMMIT/ROLLBACKするか)を明確にする

まとめ

COMMITとROLLBACKは単なる確定・取り消しではなく、アプリケーション全体の整合性と性能を左右する設計要素です。頻度・単位・例外処理・暗黙コミットへの注意を組み合わせ、最小のリスクで最大の信頼性を確保するのが正しい使い方です。