【まとめ】ACID特性・BASE基準・CAP定理

RDBとNoSQLについて学習中に躓いたため、整理します。
間違いがあったら容赦なく指摘してください。というか教えてくださいお願いします。

# ACID特性
　トランザクションシステムを有するデータベースの信頼性を保証する「トランザクションの特性」のこと。

<details> <summary> <b> A (Atomicity | 原子性) </b> </summary>
　トランザクションの間に、何らかの部分がうまくいかなかった場合に、そのトランザクションは中止され、それまでの変更がロールバックされる。つまり、そのトランザクションがなかったことになる。
 
　さながら、 **1つの原子が「存在するか」「存在しないか」 のように、処理の塊 (トランザクション) が任意の場所で分解しない** こと。
</details>

<details> <summary> <b>  C (Consistency | 一貫性, 整合性) </b> </summary>
　例えば、同じデータベース内のテーブルAの総売上と、テーブルBの総売上が異ならないといったように、一意キーを介したテーブル間で矛盾がない状態になっていること。
</details>

<details> <summary> <b> I (Isolation | 独立性, 隔離性, 分離性) </b> </summary>
　複数のトランザクションを同時に実行した際に、個々のトランザクションは他のトランザクションを意識しない、つまり無関心だということ。
 </details>

<details> <summary> <b> D (Durability | 永続性) </b> </summary>
　正常に終了したトランザクションの更新結果は、障害が発生してもデータベースから消失しないこと。なんらかの復旧手段が保証されていること。
</details>

 ACID特性によって、**「完全一貫性」** のデータベースを提供する。
 

# BASE基準
　高可用性を実現するための「システムの特性」のこと。

 <details><summary><b> BA (Basically Available | 基本的に利用可能) </b></summary>
　エラーメッセージでも、他メッセージと矛盾していてもいいので、待つこと無く必ずなんらかのレスポンスがある、ということ。
</details>

<details><summary><b> S (Soft state | 厳密ではない状態遷移) </b></summary>
　時間経過に伴って、外部からの情報によりシステムや情報が変更される可能性があること。
</details>

<details><summary><b> E (Eventual consistency | 結果整合性) </b></summary>
　更新がなくなった後に、最終的にはシステムが矛盾のない状態になること。
</details>

BASE特性は、**「結果整合性」** のシステムを提供する。

# ACIDとBASE
　ACIDとBASEは一貫性と可用性の領域の両端に位置する設計思想である(※5)。ACID特性は一貫性に重点を置いたデータベースである。高可用性を実現するためにある程度の一貫性を犠牲にして生み出された思想がBASE基準である。
　ここでは、BASEはACIDを否定しているわけではない。これはACIDはDBにおけるトランザクションの特性を表しているが、BASEはシステム全体の特性を表しており (※2) 、異なるスコープでの話をしているためである。この違いはつまり、ACIDな処理を含むDBがBASE基準を満たすシステム内にあっても良いということになる。

# CAP定理
　分散型データベースにおいて求められる以下のシステムの3属性は、同時に満たすことができないという定理。

<details><summary><b> C (Consistency | 一貫性) </b></summary>
　すべてのノードで、最新のデータが同時に表示される。
</details>

<details><summary><b> A (Availability | 可用性) </b></summary>
　一部のノードで障害が発生しても生存ノードが必ず応答を返す。
</details>

<details><summary><b> P (Partition-tolerance | ネットワーク分断耐性) </b></summary>
　ネットワークが分断されて2つ以上のノード群がお互いに疎通をとれなくなっても正常に動作する。
</details>

　なぜ同時に満たせないと言えるのか？
 <details><summary> (ここをクリック！)このように考えると分かりやすい。</summary>
　まず、1つのデータベースのクローンをネットワークで繋がったもう1つのストレージに保管した場合を考える (つまり、ネットワーク上でRAID0を構成) 。 ここで、前提として <b>「ネットワークは分断されるもの」</b> としたときに、一貫性と可用性は同時に実現できるだろうか？いや、できない。なぜなら、

- <font color="blue"> 一貫性を維持しようとすれば、一方のデータベースの更新内容を知るために通信回復を待つまで応答できなくなる (=可用性を損失) </font>

- <font color="red">可用性を維持しようとすれば、通信回復まで一方のデータベースの更新内容を無視しなければならなくなる (=一貫性を損失) </font>

からである。 逆に **「一貫性と可用性は同時に実現できるもの」** とした場合、 **「ネットワークは分断されない」** という強い制約条件を要求することになる。
　つまり、いつでもネットワークは分断されうる、という現実的な問題がCAP定理の根幹を成していると考えられる。
</details>

　分散型データベースは「ネットワークで繋がっていること」が必須条件であるから、CAP定理によると以下のどちらか一方の条件を選ばなくてはならない。
- A : 可用性を犠牲にする (= いつでも利用可能というわけではないが、一貫性を保つACID特性を優先する) 
- C : 一貫性を犠牲にする (= 正しさが担保されているわけではないが、基本的に利用可能なBASE基準を優先する)  

# CP型 (A: 可用性を犠牲にする場合)
　いつでも利用可能というわけではないが、一貫性を保つACID特性を優先する場合、例えば以下の機能を用いることで実現していく。

> - ドキュメントの**ロック**で更新時にデータを保護し、他のトランザクションと矛盾が発生しないようにする。
>
> 引用元 : https://atmarkit.itmedia.co.jp/ait/articles/1801/31/news011_2.html

　ロックによって、他のトランザクションからの操作を制約するため、「一貫性」と「独立性」が実現される。

> - ドキュメントへの**タイムスタンプ**により、その時点で有効であるドキュメントのコピーのみをクエリの対象とする（MVCC：Multi-Version Concurrency Control）。
>
> 引用元 : https://atmarkit.itmedia.co.jp/ait/articles/1801/31/news011_2.html

　読み取りだけのトランザクションに対しては、ロックは必ずしも必要ではなく、MVCC(：Multi-Version Concurrency Control) で付けられるタイムスタンプによって、「一貫性」と「独立性」を維持できる。

> - 更新の**ジャーナル**で、コミット前にシステム障害が発生しても、トランザクションを再現（リプレイ）できるようにする。
>
> 引用元 : https://atmarkit.itmedia.co.jp/ait/articles/1801/31/news011_2.html

　例えば、インメモリキャッシュである、NoSQLに対して「永続性」を付与するには、ドキュメントを再現する「操作」を記録したジャーナルをディスクに保管し、障害の際にジャーナルを基に状態を再現することで実現される。

> - データは一度に全部変更されるか、あるいは全く変更されないかのいずれかとなるような**コミット処理**（ホストが複数ある場合でも）を実行する。
> 
> 引用元 : https://atmarkit.itmedia.co.jp/ait/articles/1801/31/news011_2.html

　コミット時、同時に複数のノードへコミットがあった場合「原子性」は担保されるのか？こうした場面は2相コミットによって管理されている。つまり、複数のデータベースの状態を確認し、返答によってすべてのノードをコミットするか、ロールバックするかを決定することで、原子性を確保する。


# AP型 (C: 一貫性を一部犠牲にする場合)
　BASE基準で考えられたシステムでは、最終的に矛盾してなければよいという仕組み (結果整合性) によって、高い可用性を得ることができる。
　必ずしも正しさが担保されているわけではないが、基本的に利用可能であるBASE基準を優先する場合、例えば、以下のような機能によって実現していく。

> DB-Aの状態をロックを取らずにDB-Bに伝え、DB-Bの状態が変化する。そして最終的にDB-AとDB-Bの状態が一貫性があれば良いというものです。（この処理はBASEすべての説明になってると思います。）
>
> 引用元 : https://qiita.com/suziq99999/items/2e7037042b31a77b19c8

　この例では、データの複製中は不整合な状態になりうるが、複製によってデータが分散されていつでもデータにアクセスできるようになることを示している。
　ここでの一瞬生じる不整合な状態は「Soft-State | 厳密ではない状態遷移」であると言える。だが、DB-Aの状態はロックを取らない。このことは、「Basically Available | 基本的に利用可能」な状態である。そして、最終的にはDB-AとDB-Bの状態に一貫性がある。つまり「Eventural consistency | 結果整合性」である。

 # NoSQLでの実現例
 　ここまで、CP型, AP型の機能例を見てきた。以下のサイトでは、それぞれ(+CA型)の例を表で示しているため、参照してほしい。

https://masawan-guitar.hatenablog.com/entry/2016/08/14/163447
  

# 参照
※1 [技術評論社/ キタミ式イラストIT塾 応用情報技術者 令和2年度版/ きたみりゅうじ 著](https://gihyo.jp/book/2022/978-4-297-13188-3)

※2

https://qiita.com/suziq99999/items/2e7037042b31a77b19c8

※3 

https://atmarkit.itmedia.co.jp/ait/articles/1801/31/news011.html

※4

https://ja.tak-cslab.org/archives/498

※5

https://www.infoq.com/jp/articles/cap-twelve-years-later-how-the-rules-have-changed/

※6

https://tips-memo.com/two-phase-commit

※7

https://masawan-guitar.hatenablog.com/entry/2016/08/14/163447