ACID特性の解説
原子性、一貫性、分離性、永続性を具体例で学びます。
「ACID特性の解説」はCoddyKit上の無料Coding Interview Prepレッスンです。 これはレッスン1/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはCoding Interview Prep学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 Coding Interview Prepコースには全4レッスンが含まれています。
面接官がACIDについて尋ねる理由
シニア向けの面接官が「ACIDについて順を追って説明してください」と言うとき、4つの単語を暗記しているかを試しているわけではありません。多くのユーザーが同時にアクセスしたときに、データベースが何を保証するのかを理解しているか確認したいのです。
ACIDは原子性、一貫性、分離性、永続性を表します。すべてのトランザクションデータベース(Postgres、MySQL/InnoDB、SQL Server、Oracle)は、トランザクションで実行される処理に対して、この4つの性質を保証します。
最も説得力のある回答は、それぞれの文字を、それが防ぐ具体的な障害と結び付けます。これからのシーンで、まさにそれを行います。
トランザクションとは
トランザクションとは、データベースが単一の不可分な処理単位として扱う作業のまとまりです。BEGINで開始し、1つ以上のSQL文を実行した後、COMMITで変更を確定するか、ROLLBACKですべての変更を破棄します。
典型的な例が銀行振込です。1つの口座から引き落とし、別の口座へ入金します。両方とも実行されるか、どちらも実行されない必要があります。この保証を可能にするのがトランザクションです。
BEGIN;
UPDATE accounts SET balance = balance - 100 WHERE id = 1;
UPDATE accounts SET balance = balance + 100 WHERE id = 2;
COMMIT;A = 原子性
原子性とは、トランザクションが「すべて実行されるか、まったく実行されないか」のどちらかになる性質です。いずれかのSQL文が失敗した場合や、途中でサーバーがクラッシュした場合、トランザクション内のすべての変更が、最初から実行されなかったかのようにロールバックされます。
振込の例では、引き落としが成功した後に入金が失敗しても、原子性によって引き落としも取り消されます。処理が途中までしか完了せず、お金を失うことはありません。
面接での表現:「原子性により、トランザクションは全体としてコミットされるか、まったくコミットされないため、中途半端な状態が残りません」
原子性の動作例
ここでは、2つ目の更新がチェック制約(残高を負にできない)に違反しています。データベースはトランザクションを中止し、ROLLBACKによって1つ目の更新も取り消します。
面接で重要なのは、ロールバック後も口座1の残高が元のままである点です。テーブルに中途半端な書き込みが残ることはありません。
BEGIN;
UPDATE accounts SET balance = balance - 100 WHERE id = 1;
-- next line fails: balance would go below 0
UPDATE accounts SET balance = balance - 999999 WHERE id = 2;
ROLLBACK; -- account 1 is restored to its original balanceC = 一貫性
一貫性とは、トランザクションによってデータベースが、ある正しい状態から別の正しい状態へ移行する性質です。コミットされるすべてのトランザクションは、定義されている制約、外部キー、トリガー、カスケードなど、すべてのルールに従う必要があります。
トランザクションによって制約違反(孤立した外部キー、主キーの重複、CHECKの失敗など)が発生する場合、データベースはそのコミットを拒否します。
補足:データベースが強制するのは宣言されたルールです。一方、アプリケーションレベルの不変条件(「1人のユーザーが持てるアクティブなセッションは最大3つ」など)は、制約としてモデル化しない限り、アプリケーション側で管理する必要があります。
制約によって強制される一貫性
一貫性は、主にスキーマに定義したルールの積み重ねによって実現されます。以下では、外部キーによって、存在しない顧客の注文を登録できないことが保証されています。
存在しない顧客を参照して登録しようとすると、トランザクションが失敗し、原子性によってロールバックされるため、一貫性が維持されます。面接で原子性と一貫性は連携して働くと説明されるのはこのためです。
CREATE TABLE orders (
id INT PRIMARY KEY,
customer_id INT NOT NULL REFERENCES customers(id),
amount NUMERIC(10,2) CHECK (amount > 0)
);
-- This fails if customer 999 does not exist, keeping data consistent
INSERT INTO orders (id, customer_id, amount) VALUES (1, 999, 50.00);I = 分離性
分離性とは、同時に実行されるトランザクション同士が互いの処理を妨げない性質です。理想的には、数十個のトランザクションが同時に実行されていても、それぞれが単独で実行されたかのように動作します。
実際のデータベースでは、厳密さと性能のバランスが異なる複数の分離レベルが提供されています。弱い分離レベルでは、より高い同時実行性と引き換えに、特定の異常(ダーティリードやファントムリードなど)が許容されます。
分離性はACIDに関する面接で最も掘り下げられやすい分野です。そのため、次の2つのレッスンで分離レベルと読み取り異常を詳しく扱います。
分離性が段階的である理由
完全な分離(SERIALIZABLE)は、あらゆるインターリーブによる競合を防ぐ必要があるため、コストが高くなります。通常は、トランザクションをロックするか中止することで実現します。
そこでSQL標準では、4つの分離レベルを定義しています。面接でよくある落とし穴は、分離性を二択で考えてしまうことです。実際には二択ではありません。どの程度の分離性を求めるかを明示的に選択します。
READ UNCOMMITTED最も弱いREAD COMMITTEDREPEATABLE READSERIALIZABLE最も強い
BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE;
SELECT SUM(balance) FROM accounts;
-- ... business logic ...
COMMIT;D = 耐久性
耐久性とは、トランザクションがコミットされると、その変更がクラッシュや電源障害、再起動の後も失われない性質です。コミット済みのトランザクションは、永続ストレージに保存されています。
データベースは先行書き込みログ(WAL)によってこれを実現します。データファイルを更新する前に、変更を耐久性のあるログへ書き込みます。再起動時には、エンジンがログを再生し、まだメインファイルに反映されていなかったコミット済みの処理を復旧します。
面接での表現:「耐久性はWALによって保証されます。コミットは、ログレコードがディスクへフラッシュされた後にのみ完了します」
銀行振込に4つの性質を当てはめる
1回の振込で、4つの性質を同時に確認できます。
- 原子性: 2つの更新が両方とも適用されるか、どちらも適用されません。
- 一貫性: CHECKによって残高が負にならないように保たれます。
- 分離性: 同時実行中の読み取り処理から、途中までしか完了していない振込が見えることはありません。
- 耐久性: COMMIT後は、新しい残高がクラッシュ後も維持されます。
1つの具体例を4つの文字すべてに結び付けて説明できることが、面接で評価されるポイントです。
BEGIN;
UPDATE accounts SET balance = balance - 100
WHERE id = 1 AND balance >= 100;
UPDATE accounts SET balance = balance + 100 WHERE id = 2;
COMMIT;よくある追加質問
面接官は、概念の境界についてよく質問します。次の質問に答えられるようにしておきましょう。
- 「外部キーが強制する性質はどれですか」一貫性です。
- 「トランザクションの途中でサーバーがクラッシュした場合、何が保護してくれますか」原子性(未コミットの変更のロールバック)と、耐久性(コミット済みの変更の再生)です。
- 「分離性にコストはかかりませんか」いいえ。より強い分離性には、同時実行性の低下というコストがあります。
- 「NoSQLストアはACIDを提供しますか」多くは可用性(BASE)と引き換えにするため、エンジンによります。
理解度チェック
ACIDの各性質が何を意味するのか、理解できているか確認しましょう。
まとめ: ACIDを一息で説明する
これで、次のように明確に答えられます。
- 原子性 - すべて実行されるか、まったく実行されないか。途中までの処理はロールバックされます。
- 一貫性 - すべてのコミットが制約に従い、正しい状態を残します。
- 分離性 - 同時実行されるトランザクション同士が互いを壊しません。厳密さは調整できます。
- 耐久性 - コミット済みのデータは、先行書き込みログによって保護され、クラッシュ後も維持されます。
それぞれの文字を、それによって防げる具体的な障害と結び付けて覚えれば、並行性に関する面接の冒頭を自信を持って乗り切れます。
よくある質問
「ACID特性の解説」レッスンは無料ですか?
はい。「ACID特性の解説」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、Coding Interview Prepコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 Coding Interview Prepコースには全4レッスンが含まれています。
「ACID特性の解説」で何を学びますか?
原子性、一貫性、分離性、永続性を具体例で学びます。 ブラウザで直接実行するハンズオンコードでCoding Interview Prepを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。
Coding Interview Prepを始めるのに経験は必要ですか?
事前経験は必要ありません。CoddyKitのCoding Interview Prepは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン1/4です。
「ACID特性の解説」レッスンにはどのくらい時間がかかりますか?
ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。
このCoding Interview Prepレッスンでコードを書いて実行できますか?
はい。すべてのCoding Interview Prepレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。