トランザクションとACID

トランザクションとは

トランザクションは、複数のデータベース操作をひとまとまりの処理として扱う仕組みです。「全部成功したら確定、途中で失敗したら全部なかったことにする」— この二択しかない、というのがポイントです。

定番の例が銀行の振込です。「Aさんの口座から1万円引く」「Bさんの口座に1万円足す」の2つの更新は、片方だけ成功すると口座残高が合わなくなります。トランザクションで包めば、途中で障害が起きても中途半端な状態が残りません

ACID特性

トランザクションが満たすべき4つの性質の頭文字が ACID(アシッド)です。

特性意味
Atomicity(原子性)全部成功か全部失敗か。中間はない
Consistency(一貫性)実行前後でデータの整合性ルールが守られる
Isolation(独立性)同時に動く他のトランザクションから干渉されない
Durability(永続性)確定(コミット)した結果は障害でも失われない

[[リレーショナルデータベース]] はこの ACID を保証することを大きな特徴としています。電源が落ちても永続性(D)が守られるのは、変更を先にログへ書いてから反映する [[トランザクションログとWAL]] の仕組みがあるからです。

使い方 — BEGIN / COMMIT / ROLLBACK

[[SQL]] では次の3つの命令でトランザクションを制御します。

BEGIN;                                        -- トランザクション開始
UPDATE accounts SET balance = balance - 10000 WHERE name = 'A';
UPDATE accounts SET balance = balance + 10000 WHERE name = 'B';
COMMIT;                                       -- 確定(失敗時は ROLLBACK)
  • COMMIT(コミット)— ここまでの変更をまとめて確定する
  • ROLLBACK(ロールバック)— ここまでの変更を取り消して開始前の状態に戻す

アプリケーションのコードでは「try で更新 → 成功なら COMMIT、例外が出たら ROLLBACK」という形が定番です。

初学者向けポイント

  • 独立性(I)を厳密にするほど同時実行性能は下がる — 各データベースには分離レベルという調整段階があり、トレードオフを選べる
  • 同時更新の制御には内部でロックが使われる — 詳細は [[ロックとデッドロック]] を参照
  • トランザクションを長く開きっぱなしにしない(ロックが他の処理を待たせる)。必要な範囲だけ短く包むのが基本
  • 複数サーバーにまたがる分散環境では ACID の完全な保証が難しくなる — 1つの分散データベース内部での整合性の考え方は [[CAP定理と分散データベース]]、複数サービスにまたがる更新をアプリ側でどうつなぐかは [[分散トランザクションとSaga]] が扱う

関連技術とのつながり

  • [[リレーショナルデータベース]] — ACID 保証は RDB の看板機能
  • [[SQL]] — BEGIN / COMMIT / ROLLBACK で制御する
  • [[ロックとデッドロック]] — 独立性を実現する裏側の仕組み
  • [[CAP定理と分散データベース]] — 分散環境での整合性の考え方
Q: トランザクションの基本的な性質はどれ?
- [x] 全部成功か全部なかったことにするかの二択になる
- [ ] 成功した操作だけが部分的に反映される
- [ ] 読み取り専用の操作しか含められない
解説: 途中で失敗したら全体を取り消す(原子性)ことで、振込の片側だけ反映されるような中途半端な状態を防ぎます。

Q: ACID の A(Atomicity)が意味するものはどれ?
- [ ] 確定した結果が障害でも失われないこと
- [ ] 他のトランザクションから干渉されないこと
- [x] 全部成功か全部失敗かで中間がないこと
解説: A は原子性です。永続性は D(Durability)、独立性は I(Isolation)が対応します。

Q: 途中まで行った変更を取り消して開始前の状態に戻す命令はどれ?
- [ ] COMMIT
- [x] ROLLBACK
- [ ] BEGIN
解説: ROLLBACK は変更の取り消し、COMMIT は確定、BEGIN はトランザクションの開始です。