Caution

お使いのブラウザはJavaScriptが実行できない状態になっております。
当サイトはWebプログラミングの情報サイトの為、
JavaScriptが実行できない環境では正しいコンテンツが提供出来ません。
JavaScriptが実行可能な状態でご閲覧頂くようお願い申し上げます。

  1. トップページ
  2. SQL辞典
  3. TRANSACTION / COMMIT / ROLLBACK

TRANSACTION / COMMIT / ROLLBACK

トランザクションは複数のSQL操作をひとまとまりとして扱う仕組みです。すべて成功すれば確定(COMMIT)し、失敗すれば全体を取り消す(ROLLBACK)ことでデータの整合性を保ちます。

構文
-- トランザクションを開始します(MySQL)。
START TRANSACTION;

-- トランザクションを開始します(標準SQL・PostgreSQL)。
BEGIN;

-- 変更を確定します。
COMMIT;

-- 変更をすべて取り消します。
ROLLBACK;

-- セーブポイントを設定します。
SAVEPOINT セーブポイント名;

-- セーブポイントまで取り消します。
ROLLBACK TO SAVEPOINT セーブポイント名;
構文一覧
構文概要
START TRANSACTIONトランザクションを開始します(MySQL)。自動コミットが無効化されます。
BEGINトランザクションを開始します(標準SQL・PostgreSQL)。MySQLでも使用できます。
COMMITトランザクション内のすべての変更を確定してデータベースに永続化します。
ROLLBACKトランザクション内のすべての変更を取り消し、開始前の状態に戻します。
SAVEPOINT 名前トランザクション内に中間地点を設定します。後から部分的にロールバックできます。
ROLLBACK TO SAVEPOINT 名前指定したセーブポイントの時点まで変更を取り消します。トランザクション自体は継続します。
サンプルコード
-- 送金処理:A口座からB口座へ10,000円を移す例です。
START TRANSACTION;

UPDATE accounts SET balance = balance - 10000 WHERE account_id = 1;
UPDATE accounts SET balance = balance + 10000 WHERE account_id = 2;

-- 両方の UPDATE が成功したら確定します。
COMMIT;

-- エラーが発生した場合は取り消します(アプリケーション側で分岐)。
-- ROLLBACK;

-- セーブポイントを活用した例です。
START TRANSACTION;

INSERT INTO orders (customer_id, total) VALUES (101, 15000);
SAVEPOINT after_order;

INSERT INTO order_products (order_id, product_id, quantity) VALUES (LAST_INSERT_ID(), 5, 2);

-- この INSERT だけ取り消して注文ヘッダは残します。
ROLLBACK TO SAVEPOINT after_order;

COMMIT;
実行結果
-- COMMIT 前後の accounts テーブルの状態(例)
-- COMMIT 前(トランザクション内での見え方):
-- +------------+---------+
-- | account_id | balance |
-- +------------+---------+
-- |          1 |   40000 |  -- 50000 - 10000
-- |          2 |   30000 |  -- 20000 + 10000
-- +------------+---------+

-- ROLLBACK した場合(変更なし):
-- +------------+---------+
-- | account_id | balance |
-- +------------+---------+
-- |          1 |   50000 |
-- |          2 |   20000 |
-- +------------+---------+
データベース別の書き方

MySQL では『START TRANSACTION』または『BEGIN』でトランザクションを開始します。

START TRANSACTION;
UPDATE accounts SET balance = balance - 10000 WHERE account_id = 1;
UPDATE accounts SET balance = balance + 10000 WHERE account_id = 2;
COMMIT;

PostgreSQL では『BEGIN』でトランザクションを開始します。『START TRANSACTION』も使用できます。

BEGIN;
UPDATE accounts SET balance = balance - 10000 WHERE account_id = 1;
UPDATE accounts SET balance = balance + 10000 WHERE account_id = 2;
COMMIT;

Oracle ではトランザクションは暗黙的に開始されます(自動コミットではない)。DML文を実行した時点でトランザクションが始まり、『COMMIT』または『ROLLBACK』で終了します。

-- Oracle ではBEGIN不要(DML実行時に自動開始)。
UPDATE accounts SET balance = balance - 10000 WHERE account_id = 1;
UPDATE accounts SET balance = balance + 10000 WHERE account_id = 2;
COMMIT;

SQL Server では『BEGIN TRANSACTION』でトランザクションを開始します。

BEGIN TRANSACTION;
UPDATE accounts SET balance = balance - 10000 WHERE account_id = 1;
UPDATE accounts SET balance = balance + 10000 WHERE account_id = 2;
COMMIT;

SQLite では『BEGIN TRANSACTION』でトランザクションを開始します。デフォルトは自動コミットモードです。

BEGIN TRANSACTION;
UPDATE accounts SET balance = balance - 10000 WHERE account_id = 1;
UPDATE accounts SET balance = balance + 10000 WHERE account_id = 2;
COMMIT;
概要

トランザクションはACIDと呼ばれる4つの特性を保証します。原子性(Atomicity)・一貫性(Consistency)・独立性(Isolation)・永続性(Durability)です。特に「口座振替」「在庫引き落とし+注文登録」のような複数テーブルをまたぐ処理では、途中で失敗しても中途半端な状態が残らないよう必ずトランザクションを使いましょう。

MySQLのデフォルトは自動コミット(AUTO_COMMIT=1)モードです。『START TRANSACTION』を発行するとその間だけ自動コミットが無効になります。『SET AUTOCOMMIT = 0』で永続的に無効にすることもできますが、COMMITを忘れやすいため注意が必要です。

権限の設定・管理については『GRANT / REVOKE』を参照してください。

記事の間違いや著作権の侵害等ございましたらお手数ですがまでご連絡頂ければ幸いです。