ACID特性とトランザクション分離レベルについて

# はじめに
どうもー上司に「ACID特性って知ってるか？」と言われ、「すみません、良く分からません」とSiriみたいに答えてしまった<a href="https://yzrh.jp/" target="_blank">株式会社YUZURIHA</a>のキムです。
過去の自分を反省し、調べて理解したことをまとめてみました。

# ACID特性とは
 ACID(原子性、一貫性、独立性、永続性)はトランザクション処理の信頼性を保証するために求められる性質であるとする考え方である。

## まずは、A(Atomicity)
日本語では<b>原子性。。</b>日本にきて8年も経ってますが、聞きなれない言葉ですね。
> トランザクションに含まれるタスクが<font color="red"><b>全て実行されるか、あるいは全く実行されないことを保証する性質</b></font>です。

例えば、お友達にお金を送ったのに、お友達には届いてなかったら困りますよね。

```
// お友達にお金を送る
\DB::beginTransaction();
try {
  // お金をお友達に送金
  transferMoney($myId, $friendId);
  // 自分の口座からお金が減る 
  recalculationAccount($myId); 
  // お友達の口座にお金が増える
  recalculationAccount($friendId);
  // 全てのタスクが実行されたらデータベースに反映される  
  \DB::commit(); 
}catch (\Exception $e) { 
  // 例外発生時は巻き戻し、データベースに反映されない
  // エラー内容表示
  \DB::rollback();
  // ログを残す
  \Log::error($e);
} 
```

上記のようにトランザクション内に複数のタスクがあって、全て実行された場合のみ<font color="blue">COMMIT;</font>
一つでも実行されなかったら<font color="blue">ROLLBACK;</font>
このように全て行われるか、あるいは全く行われないことを指します。
![キャプチャ.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2961058/a46aa430-25ae-e21e-ae90-f77d843290fa.png)


## お次は、C(Consistency)
日本語では<b>一貫性</b>あるいは<b>整合性</b>とも呼ばれる。
> トランザクション開始と終了時にあらかじめ<font color="red"><b>与えられた整合性を満たすことを保証する性質</b></font>です。

例えば、主キーである口座番号が二つ存在したり、残高よりも高い買い物ができたり、処理中にデータベース内のデータに矛盾がないことを常に保証してくれていることを指します。

![キャプチャ2.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2961058/a676ea9f-ef58-97e9-0085-a719ff6836e5.png)


## あと少し、I(Isolation)
日本語では<b>分離性、独立性</b>または<b>隔離性</b>ともいう。
> 全てのトランザクションは<font color="red"><b>他のトランザクションから分離、独立することを保証する性質</b></font>です。

複数のトランザクションが同時に実行されても、結果は変わらないことを指します。
例えば、下記では実行中のトランザクション以外は、<b>送金前</b>と<b>送金後</b>のいずれかの状態しか観測できません。
<table>
  <tr><th>時点</th><th>自分の口座</th><th>お友達の口座</th>
  <tr><td>送金前</td><td>10万円</td><td>20万円</td></tr>
  <tr><td>実行中</td><td>9万円</td><td>20万円</td></tr>
  <tr><td>送金後</td><td>9万円</td><td>21万円</td></tr> 
</table>

ただし、トランザクションには分離レベルがございまして、内容をまとめてみました。
### Isolation level
一般的なDBMSはRead Commitedを使用
MySQLはRepeatable Readを使用
<table>
<tr>
  <th colspan="2">分離レベル</th><th>Dirty Read</th><th>Non-Repeatable Read</th><th>Phantom Read</th>
</tr>
<tr>
  <th>0</th><td>Read Uncommitted</td><td style="text-align:center">〇</td><td style="text-align:center">〇</td><td style="text-align:center">〇</td>
</tr>
<tr>
  <th>1</th><td>Read Commited</td><td style="text-align:center">X</td><td style="text-align:center">〇</td><td style="text-align:center">〇</td>
</tr>
<tr>
  <th>2</th><td>Repeatable Read</td><td style="text-align:center">X</td><td style="text-align:center">X</td><td style="text-align:center">〇</td>
</tr>
<tr>
  <th>3</th><td>Serializeable</td><td style="text-align:center">X</td><td style="text-align:center">X</td><td style="text-align:center">X</td>
</tr>
</table>
※英語ができる方は名前でわかると思います。<strike>私はちゃんと調べました。</strike>

#### Dirty Read
- トランザクション<b>実行中に更新したまだCOMMITされてないデータ</b>を他のトランザクションから読み取ることができる

#### Non-Repeatable Read
- トランザクション内で<b>同じデータを2回読み取った時、値が異なる</b>
- トランザクション<b>実行中にレコードの更新、削除ができるため</b>起こる現象

#### Phantom Read
- トランザクション内で<b>同じデータを2回読み取った時、最初のクエリにはなかったレコードが現れる</b>
- トランザクション<b>実行中にレコードの追加ができるため</b>起こる現象

![キャプチャ3.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2961058/db298792-26da-118c-29f4-b33704f3534c.png)


## ラスト、D(Durability)
日本語では<b>永続性</b>あるいは<b>持続性</b>と呼ばれる。
> トランザクション操作の<font color="red"><b>完了通知をユーザが受けた時点で、その操作は永続的となり、結果が失われないこと</b></font>を指す。

何らかの被害が発生しても、ログやバックアップなどで正常に終わった時点に復旧できる手段があることを指します。
<strike>人的ミスなどどうしようもない被害もあります。</strike>
![キャプチャ4.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2961058/5d803a5d-bfb1-1c80-38f1-f919f88187ad.png)


# さいごに
<font color="red"><b>「〇〇って知ってるか？」恐るべし</b></font>
下記のサイトを参考させていただきました。
https://ja.wikipedia.org/wiki/ACID_(%E3%82%B3%E3%83%B3%E3%83%94%E3%83%A5%E3%83%BC%E3%82%BF%E7%A7%91%E5%AD%A6)

https://dev.mysql.com/doc/refman/8.0/en/set-transaction.html

https://dev.mysql.com/doc/refman/8.0/en/innodb-transaction-isolation-levels.html

https://gyoogle.dev/blog/computer-science/data-base/Transaction.html

https://gyoogle.dev/blog/computer-science/data-base/Transaction%20Isolation%20Level.html