おっさんがACIDとかBASEとかまとめておく。

# はじめに
なんか真面目な話にしてしまった事を軽く後悔してます。
なんか空気読めて無くてごめんなさい。

このネタって恐らく7,8年前には語り尽くされた感ありますが、最近DBの質問をよくうけて且ついろんな製品を組み合わせて云々かんぬんみたいな相談があったりで、自分で喋っててアレ？そうだっけか？みたいな疑問が起きたりで頭の整理の為に書きました。
おっさんの理解はこの程度ですが、間違ってたら優しく突っ込んでください。

おっさんはこの業界に入ったばかりの頃、ACIDと初めてきいたときにインコグニートが浮かんだくらいのおっさんです。

そんなおっさんなりに今まで学習した内容をまとめてみました。

#ACID特性
トランザクションシステムはもっとこうよっていう特性です。
逆にいうとコレがないとトランザクションとしては信頼できないっていうものです。
MySQLやPostgreSQL,Oracle等の関係データベース管理システム（RDBMS）ではACID特性に基づいたトランザクション処理を行いますので身近だと思います。

よく銀行の送金処理を例に説明されますが、あれを使わずに行きたいと思います。

その例が良い人は https://ja.wikipedia.org/wiki/ACID_(コンピュータ科学) をどうぞ。

## **A** は atomicity

日本語では原子性とかいいます。この言葉結構好き。
<font color=red>**トランザクション内の操作が全て実行されるか/されないかを保証します**</font>

これ以上分解してくれるなっていう意味で原子性というのですが、なんのこっちゃって思うかもしれません。僕はそう思いました。
要は中途半端は許さないってことです。

トランザクションよりも小さい単位で操作を分解しちゃダメということです。
途中まで実行して、後はしらんとかじゃ困りますよね。

具体例は、`COMMIT;` ですべて実行、 `ROLLBACK;` ですべて実行しない（巻き戻し）。

ぬぉ・・・もう銀行の例をだしたい。。。。

## **C** は consistency
日本語だと一貫性です。
用法としては一貫性が担保できないじゃん！みたいな感じです。
<font color = red>**これは整合性とも言いますが、DB内のデータに矛盾のない事を常に保証します。**</font>
トランザクション内で矛盾を発生させるようなことは許容されないです。
100円しかもってないのに120円のものを買おうとすると追い返されるような感じです。

銀行の例ってまじですごいなぁ・・・

## **I** は isolation
独立性とか訳されますが、RDBMSを使ってる人からすると分離性の方がわかりやすいと思います。
トランザクション分離レベルとか良く聞くと思うのですがアレと関係してます。
割と重要なので、厚めに説明します。

トランザクション分離レベルのめんどくさい話を抜きにすると、
<font color=red>**トランザクション中に行われる操作は他のトランザクションに影響を与えない事を保証します。**</font>

具体的にはトランザクション処理中に色々イジってる値をを外部からは見ることができません、 = 外部から見れるのは処理前と処理後の状態のみです。

これを完全に保証するには直列処理するしかないのですが、それやってると性能でないので、世にあるRDBMSはココだけは手加減して実装してます。

トランザクション分離レベルという概念をANCIが定義しており下の表はそれをまとめたものです。
この4つのレベルのうちread committedかrepeatable readのどちらかをデフォルトとしているRDBMS製品が多いです。
ダーティリードとかファントムリード等は分離性を保証するのであれば、本来隠蔽しなくてはならないものです。
実は製品によっては実際に起こる起こらないがANSI定義よりも良い感じだったりするのですが、それは割愛します。

|分離レベル|ダーティーリード|ファジーリード|ファントムリード|ロストアップデート|処理速度
|:--|:--|:--|:--|:--|:--|
|read uncommitted|発生|発生|発生|発生|速い
read committed|**起きない**|発生|発生|発生|↓
repeatable read|**起きない**|**起きない**|発生|発生|↓
serializable|**起きない**|**起きない**|**起きない**|**起きない**|遅い

## **D** は durability
日本語だと永続性です。
<font color=red>**トランザクション処理結果は永続的であることを保証します。**</font>

永続的（失われない） = システム障害に耐えろということです。
**いきなり泥臭いです。**

RDBMSはトランザクションログを取っていてますよね。
ORACLEならREDOログ、MySQLならバイナリログとかいうやつです。
※実際はもう少しアレではあるが、そこは割愛
何かあっても、ログから障害発生前に戻れるようにしています。

あくまで製品の仕様であって、開発者・運用者のミスによって余裕で飛びますし、どうしょうもない障害もあります。

## おまけ
ACIDについて簡単にまとめました。
以上の特性があるので、RDBMSはいつでも安心して最新のデータを使って処理を行えます。（ここらへんを細かく話すと超めんどいのでサクッと言いました。）
ECサイトや銀行とか値がズレたりデータが飛んでしまった等が仮に発生した場合、関係者に損害を与えることが容易に想像できるサービスで使われてるのも納得かと思います。（今更感

とはいえやっぱりスケールしないよなぁ。。。ってことでBASEっていうトランザクションの考え方がでてきたんだと思います。

# CAP定理
BASEの前にCAP定理を簡単に説明します。
これは、分散処理において、ノード間のデータにおいて同時に以下3つの保証は提供できず、どうやってもどれか2つになるというやつです。ホンマかいなって色々考えたりウンウン唸ったけど、定理なので証明されており僕ごときが唸っても納得するしかなかったです。

* **C** はここでもconsistency（一貫性、いつも最新のデータが読める）
* **A** はavailability（可用性 必ずデータにアクセスできる。= 単一障害点がない）
* **Ｐ** はpartition-tolerance（ネットワークの分断への耐性。複数サーバにデータの複製がある）

具体例）
**CとAを保証**
RDBMS（クラスタ組んだの）、LDAPとか。
ネットワーク分断がおきるとCかAを捨てなければならない。 

**CとPを保証** 
単一障害点のある分散処理システムになります。
HBaseとか。（とはいうもののマスタノードをクラスタ組んだりしてどうにかこうにかやってたりはするけど、いくらかは落ちる）

**AとPを保証**
緩やかにデータ同期していくもの。わかりやすいのはDNS。他にはMySQLレプリケーション、Solrとかもそうだと思う。一貫性は保証できない。多くは結果整合性（後述）を選択している。

# BASE
ACIDはDBにおけるトランザクションの特性を表していますが、BASEはシステム全体の特性を表しています。

ここで言うシステムは最小では単一用途で分散処理を行うノード郡になるのかなと思います。例えばApache Solrを用いた検索システムとか
本来はこっちと思いますが、大きな例だとSansanが提供しているサービスを構成しているシステムとかになると思います。
ここが結構重要でBASEはRDBMSを含むシステム全体の特性であると言うことです。
なので、ACIDを否定してないです。ACIDな処理をしているDBがシステムに含まれていてもいいです。

クラウドサービスを利用する理由として**いつでも**簡単に**スケールアウト**できることがあると思います。※スケールアップはいつでも簡単とは言い難い。オンプレよか簡単ではあるけど。

これはクラウドサービスの特性としていつでもサービス提供可能でスケールアウト可能をもっているといえます。

上記特性を満たすには、CAP定理でいうところのAvailabilityとPartition-toleranceを選択する事になります。
※ 分散処理に置いて、Pは絶対に捨てられないので、Cを取るかAを取るかになります。

Consistencyを真面目に保証しようとするとスケールできないです。
ただ、Consistencyを全く保証しないのはどうなの？という事でBASEという特性を適用しています。

## **BA** はBasically Available
<font color=red>**いつでも提供可能**</font>
といっても、これはサーバをいつでも提供できるよということでは無く、Aと言う処理でBという処理が待たされないという特性です。
具体的にはキューの利用であったり、DBで言えば楽観ロックなどがこれに当たります。

## **S** はSoft-State
<font color=red>**あるノードの状態は自律的ではなく外部からの情報により変化する**</font>

なんのこっちゃと思うかもしれませんが、例えばとあるノードが壊れた場合、外部からの情報を元に復旧できます。

## **E** はEventually Consistent
<font color=red>**最終的に整合性とれてればいい。（結果整合性）**</font>

例えば別々のACIDなDB（DB-AとDB-Bとします）DB-Aの状態とDB-Bの状態を完全に一貫性のあるものにしようとすると、二相コミットが必要になります。ただそれはちょっとめんどくさいしスケールしない。それにBasically Availableではない。→ ロックが必要になる。

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

## まとめ
お気づきでしょうが、世の中のWebサービスの大半がBASEなシステムだと思うので、なーんだ知ってるよって感じでしょうが、頭の整理にはなると思います。
読んで頂きありがとうございました。