【初心者向け】SQLのCOMMITとは?使い方・トランザクションの基本・ROLLBACKとの違いも解説

データベース・SQL

データベースを操作していると、「変更を確定する」「保存する」という操作が必要になります。そんなときに使われるのがSQLのCOMMITです。

「COMMITって何のために使うの?」
「実行しないとどうなるの?」
といった疑問を持つ初心者の方も多いでしょう。

この記事では、COMMITの意味と役割、使い方、関連するトランザクション処理(ROLLBACKとの違い)まで、わかりやすく丁寧に解説します。

スポンサーリンク

COMMITって何?基本を理解しよう

COMMITの役割

COMMITは、トランザクション中のすべての変更を確定するSQL文です。

一度実行すると、変更内容はデータベースに恒久的に保存され、元には戻せません。

基本的な書き方

COMMIT;

これだけです!とてもシンプルですね。

トランザクションとは?

COMMITを理解するために、まず「トランザクション」について説明します。

トランザクションとは、複数のSQL操作を一連の処理(単位)としてまとめる機能です。

すべてが成功したときのみデータを反映し、途中で問題があればキャンセル(ROLLBACK)できます。

身近な例で理解しよう

銀行の振込を例に考えてみましょう

  1. Aさんの口座から1万円を引く
  2. Bさんの口座に1万円を足す

この2つの操作は、どちらも成功するか、どちらも失敗するかでないと困りますよね。

途中で片方だけ成功して、もう片方が失敗したら、お金が消えたり増えたりしてしまいます。

-- 振込処理の例
START TRANSACTION;  -- トランザクション開始

-- 1. Aさんの口座から1万円を引く
UPDATE accounts SET balance = balance - 10000 WHERE name = 'Aさん';

-- 2. Bさんの口座に1万円を足す  
UPDATE accounts SET balance = balance + 10000 WHERE name = 'Bさん';

-- 両方成功したら確定
COMMIT;

COMMITの必要性

COMMITなしの場合

START TRANSACTION;
UPDATE products SET price = 1000 WHERE id = 1;
-- COMMITしないで終了

→ 変更が確定されず、データが元に戻ってしまう

COMMITありの場合

START TRANSACTION;
UPDATE products SET price = 1000 WHERE id = 1;
COMMIT;  -- ここで変更が確定される

→ 変更がデータベースに保存される

COMMITの使い方と流れ

基本的なトランザクションの流れ

1. START TRANSACTION;  -- または BEGIN;
2. (SQL操作を複数実行)
3. COMMIT;            -- 成功時は確定
   または ROLLBACK;    -- 失敗時は取り消し

実際の使用例

商品購入処理

START TRANSACTION;

-- 1. 在庫を1個減らす
UPDATE products SET stock = stock - 1 WHERE id = 101;

-- 2. 売上記録を追加
INSERT INTO sales (product_id, quantity, sale_date) 
VALUES (101, 1, NOW());

-- 3. 顧客のポイントを増やす
UPDATE customers SET points = points + 10 WHERE id = 5;

-- すべて成功したら確定
COMMIT;

ユーザー登録処理

START TRANSACTION;

-- 1. ユーザー情報を登録
INSERT INTO users (name, email, password) 
VALUES ('田中太郎', 'tanaka@example.com', 'encrypted_password');

-- 2. プロフィール情報を登録
INSERT INTO profiles (user_id, age, gender) 
VALUES (LAST_INSERT_ID(), 25, '男性');

-- 3. 初期設定を登録
INSERT INTO user_settings (user_id, theme, notification) 
VALUES (LAST_INSERT_ID(), 'light', 1);

-- すべて成功したら確定
COMMIT;

データベース別の書き方

MySQL

START TRANSACTION;  -- または BEGIN;
-- SQL操作
COMMIT;

PostgreSQL

BEGIN;
-- SQL操作
COMMIT;

SQL Server

BEGIN TRANSACTION;
-- SQL操作
COMMIT TRANSACTION;  -- または COMMIT;

SQLite

BEGIN;
-- SQL操作
COMMIT;

COMMITとROLLBACKの違い

基本的な違い

操作意味使う場面結果
COMMIT変更を確定する正常に処理が完了したときデータが保存される
ROLLBACK変更を取り消す(元に戻す)エラーが起きたときデータが元の状態に戻る

ROLLBACKの使用例

エラーが発生した場合

START TRANSACTION;

-- 1. ユーザーのポイントを減らす
UPDATE users SET points = points - 100 WHERE id = 5;

-- 2. 商品の在庫を確認
SELECT stock FROM products WHERE id = 10;
-- もし在庫が足りない場合...

-- エラーなので、1の処理も取り消し
ROLLBACK;

条件チェックで失敗した場合

START TRANSACTION;

-- 残高を確認
SELECT balance FROM accounts WHERE id = 1;
-- 残高:5000円

-- 10000円引き落とそうとする
UPDATE accounts SET balance = balance - 10000 WHERE id = 1;
-- 残高がマイナスになってしまう!

-- 処理を取り消し
ROLLBACK;

実際の業務での使い分け

成功パターン(COMMIT)

START TRANSACTION;

-- 注文処理
INSERT INTO orders (customer_id, total_amount) VALUES (123, 5000);
SET @order_id = LAST_INSERT_ID();

-- 在庫減算
UPDATE products SET stock = stock - 2 WHERE id = 1 AND stock >= 2;

-- 在庫が十分あったかチェック
IF ROW_COUNT() = 1 THEN
    -- 支払い記録
    INSERT INTO payments (order_id, amount) VALUES (@order_id, 5000);
    COMMIT;  -- 成功!
ELSE
    ROLLBACK;  -- 在庫不足で失敗
END IF;

自動コミットとは?

自動コミットの仕組み

多くのデータベースでは、「自動コミット」という機能があります。

これは、SQL文を1つ実行するたびに、自動的にCOMMITされる機能です。

自動コミットがONの場合

UPDATE users SET name = '田中太郎' WHERE id = 1;
-- 自動的にCOMMITされる(元に戻せない)

自動コミットがOFFの場合

UPDATE users SET name = '田中太郎' WHERE id = 1;
-- まだ確定されていない(ROLLBACKで戻せる)
COMMIT;  -- 手動で確定する必要がある

自動コミットの設定確認と変更

MySQL

-- 現在の設定を確認
SELECT @@autocommit;  -- 1=ON, 0=OFF

-- 自動コミットを無効にする
SET autocommit = 0;

-- 自動コミットを有効にする
SET autocommit = 1;

PostgreSQL

-- PostgreSQLでは手動トランザクションが基本
-- BEGINを使わなければ各文が自動コミットされる

いつ自動コミットを無効にすべき?

自動コミットOFFが良い場面

  • 複数の操作をまとめて処理したい
  • エラー時に安全に元に戻したい
  • テスト環境でデータを確認してから確定したい

自動コミットONが良い場面

  • 単発のデータ確認や簡単な更新
  • 対話的にSQLを実行する場合

よくある間違いと注意点

COMMIT忘れによるロック

問題のある例

START TRANSACTION;
UPDATE products SET price = 2000 WHERE id = 1;
-- COMMITやROLLBACKを忘れて、セッションを閉じる

この場合、対象行がロックされたままになり、他のユーザーが同じデータを更新できなくなることがあります。

正しい例

START TRANSACTION;
UPDATE products SET price = 2000 WHERE id = 1;
-- 必ずCOMMITまたはROLLBACKで終了
COMMIT;

SELECT文にCOMMITは不要

間違った例

START TRANSACTION;
SELECT * FROM users;
COMMIT;  -- SELECTだけなら不要

正しい例

-- データを変更する場合のみトランザクションが必要
START TRANSACTION;
UPDATE users SET last_login = NOW() WHERE id = 1;
COMMIT;

長時間のトランザクション

問題のある例

START TRANSACTION;
UPDATE large_table SET status = 'processing';
-- 長時間の処理(数分〜数時間)
-- 他のユーザーがテーブルにアクセスできない
COMMIT;

改善例

-- 処理を小分けにする
START TRANSACTION;
UPDATE large_table SET status = 'processing' WHERE id BETWEEN 1 AND 1000;
COMMIT;

START TRANSACTION;
UPDATE large_table SET status = 'processing' WHERE id BETWEEN 1001 AND 2000;
COMMIT;

エラーハンドリングを忘れる

問題のある例

START TRANSACTION;
UPDATE accounts SET balance = balance - 1000 WHERE id = 1;
UPDATE accounts SET balance = balance + 1000 WHERE id = 2;
-- エラーが起きても自動でROLLBACKされない場合がある
COMMIT;

安全な例(擬似コード)

try {
    START TRANSACTION;
    UPDATE accounts SET balance = balance - 1000 WHERE id = 1;
    UPDATE accounts SET balance = balance + 1000 WHERE id = 2;
    COMMIT;
} catch (error) {
    ROLLBACK;
    throw error;
}

実際の業務でのCOMMIT活用例

ECサイトの注文処理

START TRANSACTION;

-- 1. 注文データを登録
INSERT INTO orders (customer_id, order_date, total_amount) 
VALUES (123, NOW(), 15000);
SET @order_id = LAST_INSERT_ID();

-- 2. 注文詳細を登録
INSERT INTO order_details (order_id, product_id, quantity, price) 
VALUES (@order_id, 1, 2, 5000),
       (@order_id, 2, 1, 5000);

-- 3. 在庫を減らす
UPDATE products SET stock = stock - 2 WHERE id = 1;
UPDATE products SET stock = stock - 1 WHERE id = 2;

-- 4. 顧客のポイントを増やす
UPDATE customers SET points = points + 150 WHERE id = 123;

-- 5. 在庫チェック(在庫がマイナスになっていないか)
SELECT COUNT(*) FROM products WHERE id IN (1, 2) AND stock < 0;

-- すべて正常なら確定
COMMIT;

バッチ処理での安全な大量更新

-- 毎日のポイント有効期限処理
START TRANSACTION;

-- 1. 期限切れポイントを特定
CREATE TEMPORARY TABLE expired_points AS
SELECT customer_id, SUM(points) as expired_points
FROM customer_points 
WHERE expire_date < CURDATE()
GROUP BY customer_id;

-- 2. 顧客の総ポイントから減算
UPDATE customers c
JOIN expired_points e ON c.id = e.customer_id
SET c.total_points = c.total_points - e.expired_points;

-- 3. 期限切れポイントレコードを削除
DELETE FROM customer_points WHERE expire_date < CURDATE();

-- 4. ログに記録
INSERT INTO batch_logs (process_name, affected_rows, execute_date)
VALUES ('point_expiration', ROW_COUNT(), NOW());

COMMIT;

データ移行処理

-- 旧システムから新システムへのデータ移行
START TRANSACTION;

-- 1. ユーザーデータを移行
INSERT INTO new_users (id, name, email, created_at)
SELECT user_id, user_name, email_address, registration_date
FROM old_user_table
WHERE migration_flag = 0;

-- 2. 移行済みフラグを更新
UPDATE old_user_table 
SET migration_flag = 1
WHERE migration_flag = 0;

-- 3. 移行ログを記録
INSERT INTO migration_logs (table_name, migrated_count, migration_date)
SELECT 'users', COUNT(*), NOW()
FROM new_users
WHERE created_at >= CURDATE();

COMMIT;

高度なトランザクション制御

セーブポイント(SAVEPOINT)

セーブポイントを使うと、トランザクション内で部分的なロールバックができます。

START TRANSACTION;

-- 1. ユーザー情報を更新
UPDATE users SET name = '新しい名前' WHERE id = 1;

-- セーブポイントを作成
SAVEPOINT update_profile;

-- 2. プロフィール情報を更新
UPDATE profiles SET bio = '新しい自己紹介' WHERE user_id = 1;

-- プロフィール更新でエラーが発生した場合
-- セーブポイントまで戻る(ユーザー名の更新は保持)
ROLLBACK TO update_profile;

-- 最終的に確定
COMMIT;

分散トランザクション

複数のデータベースにまたがる処理も可能です(高度な機能)。

-- データベース1での処理
START TRANSACTION;
UPDATE db1.accounts SET balance = balance - 1000 WHERE id = 1;

-- データベース2での処理  
UPDATE db2.accounts SET balance = balance + 1000 WHERE id = 2;

-- 両方が成功した場合のみコミット
COMMIT;

パフォーマンスとCOMMIT

コミット頻度の最適化

悪い例:コミットが多すぎる

-- 10万件の処理で10万回コミット(遅い)
FOR i = 1 TO 100000 DO
    START TRANSACTION;
    INSERT INTO logs VALUES (i, 'data');
    COMMIT;
END FOR;

良い例:適切なバッチサイズ

-- 1000件ずつコミット(早い)
FOR batch = 1 TO 100 DO
    START TRANSACTION;
    FOR i = (batch-1)*1000+1 TO batch*1000 DO
        INSERT INTO logs VALUES (i, 'data');
    END FOR;
    COMMIT;
END FOR;

ロック時間の最小化

START TRANSACTION;

-- 必要なデータを先に取得
SELECT balance FROM accounts WHERE id = 1 FOR UPDATE;

-- 計算処理(時間がかかる場合は先に実行)
SET @new_balance = balance - 1000;

-- 更新処理(できるだけ短時間で)
UPDATE accounts SET balance = @new_balance WHERE id = 1;

-- すぐにコミット
COMMIT;

まとめ

COMMITは、データベースにおける「変更確定」の操作であり、トランザクション処理に不可欠な存在です。

ROLLBACKとの使い分けを理解し、必要に応じて手動でトランザクションを管理することで、より安全で柔軟なデータ操作が可能になります。

重要なポイント

  • COMMIT:変更を確定する(元に戻せない)
  • ROLLBACK:変更を取り消す(元に戻す)
  • トランザクション:複数の操作をまとめて処理する仕組み
  • 自動コミット:設定によって自動的にコミットされる機能

使い方のコツ

  • 関連する複数の操作は必ずトランザクションでまとめる
  • エラー処理を忘れずに実装する
  • 長時間のトランザクションは避ける
  • 必要に応じて自動コミットの設定を調整する

よく使う場面

  • 金銭に関わる処理(振込、決済等)
  • 在庫管理
  • ユーザー登録
  • データ移行
  • バッチ処理

コメント

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