TRANSACTION / COMMIT / ROLLBACK
| 対応: | SQL-92(1992) |
|---|
トランザクションは複数のSQL操作をひとまとまりとして扱う仕組みです。すべて成功すれば確定(COMMIT)し、失敗すれば全体を取り消す(ROLLBACK)ことでデータの整合性を保ちます。
構文
トランザクションを開始します(MySQL)。
START TRANSACTION;
トランザクションを開始します(標準SQL・PostgreSQL)。
BEGIN;
変更を確定します。
COMMIT;
変更をすべて取り消します。
ROLLBACK;
セーブポイントを設定します。
SAVEPOINT savepoint_name;
セーブポイントまで取り消します。
ROLLBACK TO SAVEPOINT savepoint_name;
構文一覧
| 構文 | 概要 |
|---|---|
| START TRANSACTION | トランザクションを開始します(MySQL)。自動コミットが無効化されます。 |
| BEGIN | トランザクションを開始します(標準SQL・PostgreSQL)。MySQLでも使用できます。 |
| COMMIT | トランザクション内のすべての変更を確定してデータベースに永続化します。 |
| ROLLBACK | トランザクション内のすべての変更を取り消し、開始前の状態に戻します。 |
| SAVEPOINT 名前 | トランザクション内に中間地点を設定します。後から部分的にロールバックできます。 |
| ROLLBACK TO SAVEPOINT 名前 | 指定したセーブポイントの時点まで変更を取り消します。トランザクション自体は継続します。 |
サンプルコード
以下の『accounts』テーブルを例に説明します。
送金処理でA口座からB口座へ10,000円を移す例です。対話モードで1行ずつ実行する場合は以下のようになります。
START TRANSACTION; UPDATE accounts SET balance = balance - 10000 WHERE account_id = 1; UPDATE accounts SET balance = balance + 10000 WHERE account_id = 2; COMMIT;
COMMIT後の確定結果を確認します。桐生一馬の残高が10,000円減り、真島吾朗の残高が10,000円増えています。
SELECT * FROM accounts; +------------+----------+---------+ | account_id | name | balance | +------------+----------+---------+ | 1 | 桐生一馬 | 40000 | | 2 | 真島吾朗 | 30000 | | 3 | 秋山駿 | 75000 | +------------+----------+---------+ 3 rows in set (0.00 sec)
実務ではアプリケーション側のプログラムからトランザクションを制御するのが一般的です。.sqlファイルに記述する場合は以下のようになります。
sample_transfer.sql
START TRANSACTION; UPDATE accounts SET balance = balance - 10000 WHERE account_id = 1; UPDATE accounts SET balance = balance + 10000 WHERE account_id = 2; COMMIT;
セーブポイントを活用した例です。
sample_transaction.sql
START TRANSACTION; -- 秋山駿の残高を増やします。 UPDATE accounts SET balance = balance + 5000 WHERE account_id = 3; SAVEPOINT after_update; -- 誤って桐生一馬の残高を減らしてしまった操作をここで取り消します。 UPDATE accounts SET balance = balance - 5000 WHERE account_id = 1; -- 桐生一馬の更新だけ取り消して秋山駿の更新は残します。 ROLLBACK TO SAVEPOINT after_update; COMMIT;
Query OK, 0 rows affected (0.00 sec) Query OK, 1 row affected (0.01 sec) Query OK, 0 rows affected (0.00 sec) Query OK, 1 row affected (0.01 sec) Query OK, 0 rows affected (0.00 sec) Query OK, 0 rows affected (0.01 sec)
sample_transaction.sql
SELECT * FROM accounts;
+------------+----------+---------+ | account_id | name | balance | +------------+----------+---------+ | 1 | 桐生一馬 | 50000 | | 2 | 真島吾朗 | 20000 | | 3 | 秋山駿 | 80000 | +------------+----------+---------+ 3 rows in set
データベース別の書き方
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;
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;
概要
トランザクションが安全にデータを扱うための4つの原則を『ACID特性』と呼びます。原子性(Atomicity)・一貫性(Consistency)・独立性(Isolation)・永続性(Durability)です。特に「口座振替」「在庫引き落とし+注文登録」のような複数テーブルをまたぐ処理では、途中で失敗しても中途半端な状態が残らないよう必ずトランザクションを使いましょう。
MySQLのデフォルトは自動コミット(AUTO_COMMIT=1)モードです。『START TRANSACTION』を発行するとその間だけ自動コミットが無効になります。『SET AUTOCOMMIT = 0』で永続的に無効にすることもできますが、COMMITを忘れやすいため注意が必要です。
権限の設定・管理については『GRANT / REVOKE』を参照してください。
記事の間違いや著作権の侵害等ございましたらお手数ですがこちらまでご連絡頂ければ幸いです。