ACIDとは何ですか?ベイビー、もう傷つけないで
こんにちは、超絶デベロッパーの皆さん!👋🏻⚡️
たくさんの開発者が_MySQL_や_PostgreSQL_などのリレーショナルデータベースを使っていますね。彼らはたぶんトランザクションにも慣れ親しんでいるでしょう。しかし、この「トランザクション」とは何で、どんな特性があるのでしょうか?
今日はACIDというカッコいいけどちょっと怖い言葉にまとめられたトランザクションの特性についてお話しようと思います。そしてこの言葉のそれぞれの文字の真実を明かします👆🏻
ACIDとは何ですか?
ACIDは以下の言葉の頭文字です:
- アトミシティ (Atomicity);
- コンシステンシー (Consistency);
- アイソレーション (Isolation);
- デュラビリティ (Durability)。
もしデータベースの中である操作がこれらの特性を満たしていたら、その操作を「トランザクション」と呼ぶことができます。
いい感じですが、説明がなければこれらの言葉は単なる言葉です。それぞれの特性についてもっと詳しく見ていきましょう!🚜
アトミシティ
アトミシティとは素晴らしい特性で、トランザクションが原子性を持ち、小さな部分に分割できないことを保証しています。トランザクション内で何かが起こった場合、そのトランザクション内で記述されている影響を受けるすべてのフィールドに対して元に戻されます。
以下のクエリを想像してみてください:
START TRANSACTION;
INSERT INTO posts VALUES ('title', 'body', 'draft');
SELECT @counter := COUNT(id) FROM posts WHERE status = 'draft';
UPDATE posts_statistics SET posts_amount = @counter + 1 WHERE status = 'draft';
COMMIT;
このトランザクションは基本的に投稿を挿入し、ドラフトの状態の投稿に対するpost_statistics.posts_amount
フィールドを増やします。もしposts_statistics
のUPDATE
が失敗した場合、トランザクション全体がロールバックされ、投稿はposts
テーブルに挿入されません。従って、これら二つの操作(実際には三つですね、SELECT
も操作です)は密接に結びついており、原子性を持っていると考えることができます。
アトミシティのもう一つの素晴らしい特性は、トランザクションがコミットされるまでは、全てのクライアントがテーブルの変更を見ることができないという点です。したがって、上記のトランザクションを実行している最中に、別のクライアントからSELECT COUNT(id) FROM posts WHERE status = 'draft'
というクエリを実行した場合、@counter
変数が持っている値とは異なる値が見えるでしょう。
コンシステンシー
これはとても曖昧で不明瞭な文字です。おそらくあなたはCAP定理(CAP定理やそこでの一貫性のタイプについて知りたければコメントを残してください😌)やConsistent hashingについて聞いたことがあるでしょう。ここでのコンシステンシーは、アプリケーションレベルのデータの一貫性にもっと焦点を当てています。基本的に、トランザクションをコミットする前に、システムが事前に設定された不変条件を満たすようにし、トランザクションを開始する時点で有効であったものを確認する必要があるという意味です。
例えば、dev.toのショップで何かを買うときを想像してください。カッコいいTシャツに対して支払いをする段階にきました。全ての情報を記入してPayをクリックしました。コンシステンシー特性を満たすために、あなたのお金の合計額とdev.toのお金の合計額は、トランザクションの開始時点とコミット時点で同じでなければなりません。
この合計額はこのトランザクションにとっての不変条件と考えることができます。
アイソレーション
この特性は、いわゆる競争状態を防ぐためにデータベースがとても役立ちます。いわゆる「競争状態」とは何か疑問に思うかもしれません。
複数のクライアントが同時に同じデータにアクセスして変更しようとしている状況を想像してください。例えば、彼らがアトミシティの章で説明されたトランザクションを使って同時に投稿を挿入する場合です:
START TRANSACTION;
INSERT INTO posts VALUES ('title', 'body', 'draft');
SELECT @counter := COUNT(id) FROM posts WHERE status = 'draft';
UPDATE posts_statistics SET posts_amount = @counter + 1 WHERE status = 'draft';
COMMIT;
最初は42の投稿があったとしましょう(なぜなら42だから)。彼らが同時に行うので、以下のようなことが起こり得ます:
基本的に、彼らは自分の投稿を追加していますが、投稿の合計数は44であるべきですが、結果的に43になっています。
理想的な世界では、アイソレーション特性は並行するトランザクションが一つずつ、または_連続して_実行されるかのように見えることを保証しています。そのため、これは直列可能性としても知られています。実際には、この特性の実装はほとんど直列可能ではなく、いくつかのデータベースではいわゆる弱いアイソレーションを使用しています(詳しく知りたければコメントを残してください)。
デュラビリティ
最後ですが、非常に重要な特性がデュラビリティです。この特性は、トランザクションが正常にコミットされたら、データが電源の故障やデータベースのクラッシュで破損された場合でも、コミットされたまま保持されるということを意味します。
デュラビリティはデータベースのアーキテクチャに基づいて区別することができます:
- シングルノードデータベース;
- レプリケーションデータベース(レプリケーションについてもっと読むにはこちら)。
_シングルノードデータベース_においては、デュラビリティはデータがディスクに書き込まれることによって破損しないことを確認し、ディスクの破損の場合のリカバリーメカニズムがあることを保証しています。
_レプリケーションデータベース_においては、デュラビリティはデータがある程度のレプリカに書き込まれることを確かめ、クラッシュした場合に他のレプリカへと伝播することを保証しています。
まとめ
今日は、ACIDという言葉にまとめられた_トランザクション_の特性について学びました。
ACIDは以下の言葉の頭文字です:
- アトミシティ – すべての_トランザクション_が原子性を持ち、細かく分けることができないことを保証します;
- コンシステンシー – _トランザクション_がアプリケーションの不変条件を破ることがないことを保証します;
- アイソレーション – 競争状態が起こらないように保証します;
- デュラビリティ – 一度_トランザクション_がコミットされると、それは永遠にコミットされたままであることを保証します。
以上です!ご注目ありがとうございました!この記事が気に入っていただけたら幸いです😌
こちらの記事はdev.toの良い記事を日本人向けに翻訳しています。
https://dev.to/tutelaris/what-is-acid-baby-don-t-hurt-me-no-more-2jlb