先に要点
トランザクションって何のためにあるの?
エラーになったら自動で戻るなら、別に意識しなくてもいいのでは?
この疑問はかなり自然です。
実際、単純な 1 件更新だけなら、トランザクションを強く意識しなくても動くことがあります。
ただ、実務では 注文を作る + 在庫を減らす、ユーザーを作る + 初期設定を作る、送金元を減らす + 送金先を増やす のように、複数の処理がそろって初めて正しい という場面がかなり多いです。
こういうときに、途中まで成功して残りが失敗すると、データが壊れます。
この記事では、2026年4月14日時点で PostgreSQL 18 の Transactions 解説、MySQL 8.4 の START TRANSACTION / COMMIT / ROLLBACK、Laravel 12 の database transactions を確認しながら、トランザクション とは何か、どんなときに必要かを初心者向けに整理します。
トランザクションとは何か
トランザクション は、複数の SQL 更新をひとまとまりとして扱う仕組みです。
初心者向けにかなりざっくり言うと、一連の処理をセットで成功 / 失敗させるための箱 です。
PostgreSQL 公式ドキュメントでも、トランザクションの本質は 複数の手順を、全部成功か全部失敗かの操作として束ねること と説明されています。
途中状態は他のトランザクションから見えず、完了できなければ、それまでの更新はなかったことにできます。
この考え方が必要になるのは、中途半端な状態が残ると困る処理 です。
COMMIT と ROLLBACK は何が違うのか
トランザクションを理解するときに、まず押さえたいのはこの 2 つです。
COMMIT= 更新を確定するROLLBACK= 更新を取り消す
MySQL の公式ドキュメントでも、COMMIT は現在のトランザクションを確定し、変更を永続化すること、ROLLBACK は現在のトランザクションを取り消すこととして説明されています。
たとえば、次のような流れです。
START TRANSACTION;
UPDATE accounts SET balance = balance - 1000 WHERE id = 1;
UPDATE accounts SET balance = balance + 1000 WHERE id = 2;
COMMIT;
もし途中で問題が見つかったら、COMMIT の代わりに ROLLBACK します。
START TRANSACTION;
UPDATE accounts SET balance = balance - 1000 WHERE id = 1;
UPDATE accounts SET balance = balance + 1000 WHERE id = 2;
ROLLBACK;
これで、途中までの変更を全部取り消せます。
なぜトランザクションが必要なのか
答えはシンプルで、途中で失敗したときにデータを壊さないため です。
1 個ずつ別々に更新すると、次のような事故が起こりえます。
- 在庫だけ減って注文が作られていない
- 会員だけ作られてプロフィール初期化が失敗した
- 売上だけ記録されて請求情報が作られていない
この状態は、アプリから見ると 失敗した のに、DB から見ると 一部だけ成功している のでかなり厄介です。
実務で怖いのは、エラーが出ることそのものより、気づきにくい中途半端なデータが残ること です。
どんなときに必要か
1. 複数テーブルをまとめて更新するとき
これはかなり定番です。
たとえば EC サイトなら、
ordersに注文を作るorder_itemsに明細を作るproductsの在庫を減らす
この 3 つがそろって初めて正常です。
途中で 1 つでも失敗したら、全部戻したいです。
こういう処理はトランザクションの代表例です。
2. 1つの業務処理に複数の更新が含まれるとき
テーブルが複数でなくても必要になることがあります。
たとえば、
- 残高を減らす
- 利用履歴を残す
- 通知状態を更新する
のように、業務としては1回の操作 なのに DB 更新が複数あるケースです。
ここでも、途中まで成功して残りが失敗すると整合性が崩れます。
3. 後から直しにくい重要データを扱うとき
特に重要なのは次のようなデータです。
- お金
- 在庫
- 権限
- 契約状態
- 申込状態
このあたりは、あとから手作業で直すのが危険です。
だからこそ、最初からトランザクションで守る価値があります。
実務でありがちな具体例
例1. 会員登録と初期データ作成
ユーザー登録時に、
usersに会員を作るprofilesにプロフィール初期値を作るsettingsに初期設定を作る
という処理をすることがあります。
ここで users だけ作れて、profiles が失敗すると、ログインできるのに画面表示で落ちる、というような中途半端な状態になりやすいです。
こういう処理はひとまとまりで成功 / 失敗させた方が安全です。
例2. 注文確定と在庫更新
注文が入ったときに、
- 注文作成
- 注文明細作成
- 在庫減算
を別々にやっていると、在庫だけ減って注文が残っていない、という事故が起きえます。
EC や予約システムでは、かなり重要なポイントです。
例3. 管理画面から権限変更
管理者があるユーザーを 一般 から 管理者 に変更するときに、
- ロール更新
- 権限テーブル更新
- 監査ログ作成
のような処理をまとめて行うことがあります。
ここで権限だけ変わって監査ログが残らない、あるいは一部だけ反映されると、後から追跡しにくくなります。
トランザクションが不要な場面もある
何でもトランザクションに入れればよいわけではありません。
たとえば、
- 単純な 1 件更新だけ
- 一覧取得だけの処理
- 失敗しても再実行すればよい補助的な処理
なら、必ずしも大きなトランザクションは要りません。
特に初心者がやりがちなのは、不安だから全部トランザクションに入れる ことです。
でも実務では、どこからどこまでを1つの業務処理として守りたいのか を先に考える方が大事です。
Laravel ではどう書くのか
Laravel 公式ドキュメントでは、DB::transaction() を使って、クロージャ内の処理をトランザクションとして実行できます。
例外が投げられた場合は自動でロールバックされ、成功すれば自動でコミットされます。
たとえば次のような形です。
use Illuminate\Support\Facades\DB;
DB::transaction(function () {
// 注文作成
// 在庫更新
// 履歴保存
});
Laravel を使っていると、この書き方でかなり扱いやすくなります。
ただし、どの処理を同じトランザクションに含めるべきか までは自動では決まりません。
ここはアプリ設計側で考える必要があります。
よくある誤解
トランザクションを使えば何でも安全?
そこまでは言えません。
DB 更新のまとまりは守れますが、外部 API 呼び出しやメール送信まで完全に巻き戻せるわけではありません。
たとえば、
- DB には保存した
- でも外部決済 API が失敗した
のようなケースでは、DB トランザクションだけでは足りません。
別の再試行設計や補償処理が必要になることがあります。
エラーが出たら勝手に全部戻る?
フレームワークの書き方や DB 接続の扱い次第です。
Laravel の DB::transaction() のように明示的な仕組みを使うと分かりやすいですが、何も考えずに複数更新を書くだけでは、期待通りにまとまらないことがあります。
長いトランザクションほど安心?
これも違います。
必要以上に長いトランザクションは、ロックや競合の原因になりやすく、他処理へ影響することがあります。
守るべき処理だけを、必要な範囲でまとめる方が実務では大事です。
初心者が最初に意識したいこと
最初は次の 3 つを押さえるだけでもかなり違います。
- この処理は途中で失敗したら困るか
- 複数の更新がそろって初めて正しいか
- 失敗したときに全部戻したいか
この 3 つが はい なら、トランザクションを検討した方がよいです。
まとめ
トランザクション は、複数の更新を 全部成功させるか、全部なかったことにするか でまとめる仕組みです。
途中で失敗したときに、中途半端なデータを残さないために使います。
特に、注文と在庫、会員登録と初期設定、権限変更と監査ログのように、複数の更新がそろって初めて正しい処理 ではかなり重要です。
COMMIT は確定、ROLLBACK は取り消し、という基本を押さえておくとかなり理解しやすくなります。
Laravel などのフレームワークを使うと書き方はかなり楽ですが、大事なのは どこからどこまでを1つの業務処理として守るか を考えることです。
データベース全体の見方をもう少し広げたいなら PostgreSQLとMySQLの違いは?実務でどう選ぶかを初心者向けに比較、データ操作をアプリ側からどう扱うかは ORMとは?何が便利?SQLを知らなくていいわけではない理由を初心者向けに解説 もつながりやすいです。
参考リンク
- PostgreSQL Documentation: Transactions
- MySQL 8.4 Reference Manual: START TRANSACTION, COMMIT, and ROLLBACK Statements
- Laravel 12.x Docs: Database Transactions