コンピューターサイエンス:アルゴリズム / OS / ネットワーク / DB
ACID 特性
ACID 特性
このレッスンで分かること
- ACID という 4 文字の正体
- 各特性が「何の事故を防ぐか」
- 内部実装(WAL、ロック、MVCC、fsync)との対応
ACID 特性 とは
Atomicity / Consistency / Isolation / Durability を内部から理解。
ACID とは
ACID はトランザクションが備えるべき 4 つの性質の頭文字です。
- A — Atomicity(原子性)
- C — Consistency(一貫性)
- I — Isolation(独立性、分離性)
- D — Durability(永続性)
これらが揃って初めて「業務システムで使える DB」と言えます。
Atomicity(原子性)
「すべて成功するか、すべて失敗するか」という性質です。前のレッスンで見た「銀行送金で 1000 円が消失しない」のは原子性のおかげです。
実装は WAL (Write-Ahead Log) と呼ばれる先行書き込みログです。
- 変更を WAL に書く(まだ本体には書かない)
- WAL に
COMMITレコードを書く - その後、本体ファイルに反映する
- 途中でクラッシュしたら、再起動時に WAL を見て「
COMMITまで到達したものだけ」適用する
COMMIT まで書かれていない変更は破棄されます。これで原子性が保証されます。
Consistency(一貫性)
トランザクション開始前と終了後で、データが DB の整合性ルール を満たしている、という性質です。
具体的なルールは次のものです。
PRIMARY KEY、UNIQUE、NOT NULLなどの制約FOREIGN KEYの参照整合性CHECK制約- アプリケーションが定めた業務ルール(残高は 0 以上、など)
トランザクションの中でこれらが一時的に破られることがあっても、最終的にコミット時に整合性を満たしていなければなりません。違反するとコミットが失敗し、自動で ROLLBACK されます。
Consistency は「DBMS とアプリの共同責任」。DBMS は制約違反を弾くが、業務ルールの一貫性はアプリが守る。
Isolation(分離性)
同時に走る複数トランザクションが、互いに干渉しない という性質です。
例えば Alice と Bob が同時に同じ商品の在庫を 1 つずつ買おうとしたとき、在庫が 1 個しかなければどちらか一方しか成功してはいけません。
これを実現するには ロック や MVCC が必要です。完全な分離(直列実行と同じ結果)を達成すると性能が落ちるため、現実には複数の 分離レベル から選択する設計になっています。次のレッスンで詳しく扱います。
Durability(永続性)
COMMIT が返ってきた変更は、たとえサーバが直後にクラッシュしても消えない という性質です。
実装はやはり WAL です。WAL を ディスクに fsync してから COMMIT OK を返します。fsync は OS のキャッシュをディスクの物理メディアまでフラッシュするシステムコールです。これが遅いので、書き込み性能のボトルネックになります。
最近のクラウド DB (TiDB、Spanner、Aurora など) は、ログを 複数ノードに同期書き込み することで永続性を担保します。1 ノードが消えても、別ノードのログから復旧できる仕組みです。
ACID と性能のトレードオフ
ACID を完全に保証すると性能が落ちます。各 DB は次のチューニングつまみを提供します。
- fsync 頻度 — MySQL の
innodb_flush_log_at_trx_commitを1から2にするとコミットごとに OS のファイルキャッシュへ書くがfsyncは約 1 秒に 1 回になる。MySQL プロセスのクラッシュではデータは失われないが、OS やサーバごと落ちると最大約 1 秒分のコミットが失われうるリスクと引き換えに数倍速くなる - 分離レベル —
SERIALIZABLEからREAD COMMITTEDに下げると並列性が上がる - 同期レプリケーション → 非同期 — レプリへの書き込みを待たないことで応答速度を上げる
性能を欲張りすぎると、ACID のどれかが弱まり事故が起きます。業務要件と相談して 設定すべきです。
NoSQL の BASE
NoSQL の多くは ACID ではなく BASE を採用します。
- Basically Available(基本的に使える)
- Soft state(状態は変動しうる)
- Eventually consistent(最終的には整合)
これは「整合性を一時的に諦めて可用性を取る」設計です。AP 系の分散システムが採用します。SNS のいいね数が一瞬古くても問題ない用途には向きますが、金融トランザクションには向きません。
やってみよう
- MySQL で
innodb_flush_log_at_trx_commitの値を確認する(デフォルト 1) INSERTを 10000 件、自動コミットありとなしで時間比較する- 「銀行残高が常に 0 以上」という制約を
CHECK (balance >= 0)で表現し、違反するUPDATEを試す
よくある質問
Q. ACID とは何の略ですか?
A. Atomicity(原子性)、Consistency(一貫性)、Isolation(分離性)、Durability(永続性)の頭文字です。トランザクションが満たすべき 4 つの性質で、銀行系のように壊れてはいけないデータを扱う場合の基本要件になります。
Q. Isolation Level の違いは?
A. READ UNCOMMITTED < READ COMMITTED < REPEATABLE READ < SERIALIZABLE の順に厳しくなり、性能は逆順に下がります。MySQL のデフォルトは REPEATABLE READ、PostgreSQL は READ COMMITTED です。要件に応じて選択してください。
Q. BASE との違いは何ですか?
A. ACID は強整合性を即座に保証、BASE は最終的に整合する設計です。金融や予約のようにミリ秒単位の不整合も許せない場面は ACID、SNS のタイムラインのように多少の遅延が許される場面は BASE が向きます。
次のレッスン
次は 分離レベル で、Atomicity / Consistency / Isolation / Durability を内部から理解 を学びます。
事前確認 — 進む前に次の 3 つができることを確認しましょう。
- ACID 特性 の要点を自分の言葉で説明できる
- このレッスンの最小コード (または操作手順) を見ずに書ける
- 練習問題やクイズで間違えた箇所を読み直して理解した
理解度チェック (30 秒)
Q. ACID 特性 とは何か、1 文で説明してください。
A. 本文の「このレッスンで分かること」または冒頭の説明文を見直し、自分の言葉で要約できれば OK。詰まったら本レッスンの最初の H2 セクションを読み返してみましょう。
関連レッスン