TL

トランザクションと ACID

複数の処理を“全部成功か、全部なかったことにするか”の一塊として扱う仕組みと、それを支える4つの性質 ACID をやさしく解説。

中級トランザクションACIDデータベース分離レベル最終更新: 2026-06-04
TL;DR要点だけ先に
  • 1.トランザクションは複数の処理を“ひとまとまり”にして、全部成功(コミット)か全部取り消し(ロールバック)かのどちらかに揃える仕組み。
  • 2.信頼性を支える4性質が ACID:原子性(Atomicity)・一貫性(Consistency)・独立性(Isolation)・永続性(Durability)。
  • 3.並行実行の“見え方”は分離レベルで調整でき、緩めるほど速いがダーティリードなどの異常が起きやすくなる。

なぜ必要?──送金の例

「A の口座から B の口座へ 1,000 円送る」は、実は2つの更新に分かれます。

UPDATE accounts SET balance = balance - 1000 WHERE id = 'A';
UPDATE accounts SET balance = balance + 1000 WHERE id = 'B';

1行目の直後にサーバが落ちたら、A から引かれたのに B には入らない=お金が消えます。この2行を1つのトランザクションで囲み、両方成功したときだけ確定(コミット)すれば、こうした「片側だけ実行」を防げます。

BEGIN;                                                   -- トランザクション開始
UPDATE accounts SET balance = balance - 1000 WHERE id = 'A';
UPDATE accounts SET balance = balance + 1000 WHERE id = 'B';
COMMIT;                                                   -- ここで初めて確定
-- 途中で問題があれば COMMIT の代わりに ROLLBACK; で全部取り消し
  • コミット(COMMIT): 変更を確定させ、他からも見える正式な状態にする。
  • ロールバック(ROLLBACK): BEGIN 以降の変更をすべて破棄し、開始前の状態へ戻す。

ACID とは

トランザクションが満たすべき4つの性質の頭文字です。

性質意味送金での具体例
原子性 (Atomicity)全部やるか、全部やらないか。中途半端を許さない2つの UPDATE は両方反映 or 両方取消
一貫性 (Consistency)ルール(制約)を破った状態にはしない残高がマイナス禁止なら、その制約は常に保たれる
独立性 (Isolation)並行する他の処理から途中経過が見えない送金中の半端な残高を別ユーザーは見ない
永続性 (Durability)コミットしたら障害が起きても消えないCOMMIT 後はサーバ再起動でも結果が残る
一貫性は“DBが勝手に保証”ではない

一貫性(C)は、原子性・独立性・永続性と、アプリ側が定義した制約(NOT NULL、外部キー、CHECK など)やロジックの合わせ技で守られます。「残高は0以上」というルールをどこにも書かなければ、DB はマイナス残高を一貫性違反とは見なしません。ルールを宣言して初めて守られる点に注意。

並行実行と分離レベル

DB は普通、多数のトランザクションを同時にさばきます。完全に1件ずつ順番待ち(直列)にすれば安全ですが遅い。そこで「どこまで他の途中経過を見せるか」を段階的に選べるのが 分離レベル(Isolation Level) です。緩いほど速く、厳しいほど安全です。

代表的な異常(アノマリー)は次の3つ。

異常何が起きるひとことで
ダーティリード他がまだコミットしていない(取消されるかもしれない)変更を読んでしまう未確定の値を読む
ノンリピータブルリード同じ行を2回読むと、間に他のコミットが入り値が変わる同じ行の値がブレる
ファントムリード同じ条件で2回検索すると、間に挿入/削除され行数が変わるヒットする件数がブレる

SQL 標準は、これらをどこまで防ぐかで4つの分離レベルを定めています。

分離レベルダーティリードノンリピータブルファントム
READ UNCOMMITTED起きうる起きうる起きうる
READ COMMITTED防ぐ起きうる起きうる
REPEATABLE READ防ぐ防ぐ起きうる(*)
SERIALIZABLE防ぐ防ぐ防ぐ
“規格上の最低保証”と“実装”は別物

上の表は SQL 標準が定める**「最低限ここまでは防ぐ」**という線引きです。実際の DB はもっと強いことが多く、(*) を付けた REPEATABLE READ でも、たとえば PostgreSQL の実装ではファントムリードまで防ぎます。自分が使う製品の分離レベルが実際に何を保証するかは、製品のドキュメントで必ず確認しましょう。デフォルトの分離レベルも製品ごとに違います(多くは READ COMMITTED)。

“とりあえず SERIALIZABLE”は要注意

一番厳しい SERIALIZABLE にすれば異常は消えますが、その分ロック待ちや競合による再試行(シリアライズ失敗)が増え、スループットが落ちたりデッドロックが起きやすくなります。**異常を「どこで・どう防ぐか」**を考え、必要な範囲だけ分離レベルを上げるのが定石です。どう実現されるかはロックとMVCCで扱います。

つまずきポイント

長いトランザクションは“持ちっぱなし”を生む

トランザクションを開いている間、行ロックや古いバージョンのデータが保持され続けます。中で外部API呼び出しやユーザー入力待ちをすると、その間ずっと他をブロックしたり DB の掃除(バキューム)を妨げたりします。トランザクションは短く保ち、重い待ち処理は外に出すのが鉄則です。

自動コミットに気づかず“囲い忘れる”

多くのクライアントは既定で1文ごとに自動コミットします。複数の更新を一塊にしたいのに BEGIN/COMMIT で囲み忘れると、原子性は効かず「1行目だけ確定」が普通に起こります。一塊で扱いたい処理は、明示的にトランザクションで囲っているか確認しましょう。

どんな時に意識する?

  • 在庫引き当てと注文確定、ポイント減算と特典付与など、複数テーブル/複数行を矛盾なく更新したいとき。
  • 同じデータに多人数が同時アクセスし、競合の見え方を制御したいとき。
  • 関連する話として、NoSQL では強い ACID より可用性・スケールを優先する設計もあります(RDB と NoSQL)。また排他制御の中身はロックとMVCCへ。トランザクションは「正しさ」と「速さ」を天秤にかける道具であり、常に最強設定が正解ではありません。

データベース Article

トランザクションと ACIDを実務で読む

TL;DRは入口です。実際に選ぶ・使う段階では、何を解決するか、何と比較するか、導入後にどこで詰まるかまで見る必要があります。

解決すること

トランザクション

比較で見る軸

難易度: intermediate / カテゴリ: データベース / タグ数: 4

導入後に効く点

信頼性を支える4性質が ACID:原子性(Atomicity)・一貫性(Consistency)・独立性(Isolation)・永続性(Durability)。

先に潰すリスク

用語だけ覚えても、設計・実装・運用でどこに効くかを確認しないと判断を誤る。

数字・仕様の読み方
難易度
intermediate
カテゴリ
データベース
タグ数
4

判断チェックリスト

  • 自社の用途が「トランザクション / ACID」に近いか確認する。
  • 強みである「トランザクションは複数の処理を“ひとまとまり”にして、全部成功(コミット)か全部取り消し(ロールバック)かのどちらかに揃える仕組み。」が本当に評価軸になるか確認する。
  • 注意点の「用語だけ覚えても、設計・実装・運用でどこに効くかを確認しないと判断を誤る。」を運用で吸収できるか確認する。
  • 公開値や仕様値は、対象プラン・対象機種・対象リージョンまで確認する。
  • 既存システム、ID、ネットワーク、監視、バックアップとの接続方法を先に洗い出す。
  • 小さく試してから、本番移行、権限設計、障害時手順、コスト監視を決める。

次に確認する観点

トランザクションACIDデータベース分離レベルトランザクションACIDデータベース分離レベル
参考: 公式情報