処理をまとめて確定・取消 - BEGIN / COMMIT / ROLLBACK
トランザクションの開始・確定・取り消しを行う基本コマンド。ACID の I (独立性) を支える仕組み
概念図
構文
sql
BEGIN; ... COMMIT; -- or ROLLBACK;サンプル
振込処理を 1 トランザクションにまとめ、両方成功したときだけ確定する
sql
BEGIN;
UPDATE accounts SET balance = balance - 1000 WHERE id = 1;
UPDATE accounts SET balance = balance + 1000 WHERE id = 2;
COMMIT;トランザクションとは
トランザクションは 一連の SQL 操作をひとまとめにして、全て成功したときだけ確定する仕組みです。途中で失敗したら ROLLBACK ですべて無かったことにできます。
たとえば銀行振込では「引き落とし」と「入金」の両方が成功しないとデータが壊れます。トランザクションはこの「全か無か」を保証します。
ACID 特性
- Atomicity (原子性): 全部成功するか全部無かったことになる
- Consistency (整合性): 制約を壊さない状態から壊さない状態へ遷移する
- Isolation (独立性): 並行実行しても直列実行と同じ結果に見える
- Durability (永続性): COMMIT 後はクラッシュしても消えない
autocommit の RDBMS 差
- PostgreSQL: デフォルトで autocommit ON。
BEGIN明示で明示的トランザクションに入る - MySQL: デフォルトで autocommit ON (
SET autocommit=0で OFF)。START TRANSACTIONも可 - SQL Server: デフォルトで autocommit ON。
BEGIN TRAN/BEGIN TRANSACTIONで開始し、明示的COMMIT/ROLLBACKが必要 - Oracle: 常に暗黙的にトランザクション中。DML 発行時点で開始し、
COMMIT/ROLLBACKで区切る
sql
-- MySQL: autocommit を切って明示制御
SET autocommit = 0;
START TRANSACTION;
UPDATE inventory SET stock = stock - 1 WHERE id = 10;
COMMIT;
-- SQL Server
BEGIN TRAN;
UPDATE inventory SET stock = stock - 1 WHERE id = 10;
COMMIT TRAN;長時間トランザクションの危険
トランザクションを開いたまま長時間放置すると、以下の問題が起きます。
- ロックの滞留: 他セッションが待たされ、最悪デッドロック
- PostgreSQL の VACUUM 阻害: 古いバージョンのタプルが回収されず、肥大化 (bloat)
- UNDO/REDO ログの肥大: ディスク逼迫・復旧時間増加
トランザクションは短く保ち、ユーザー入力を待つ間などに開いたままにしないことが鉄則です。
エラー時の自動ロールバック
RDBMS によってエラー時の挙動が違います。
- PostgreSQL: 1 つでも文がエラーになるとトランザクション全体が「abort 状態」になり、
ROLLBACKしないと次の文を受け付けない - MySQL (InnoDB) / SQL Server: エラーになった文だけ失敗し、他の文は残る場合がある。アプリ側で明示的に
ROLLBACKが必要
アプリケーションでは必ず try/catch でエラーを捕捉し ROLLBACK を呼ぶ実装にしましょう。
