ISOLATION LEVELについて（学習メモ）

#ISOLATION LEVELについて
##ISOLATION LEVELとは（１）
トランザクションの独立性、分離性のレベルの事。ACID特性の**I**に当たる部分のレベルの事。
独立性阻害要因（１、ダーティリード２、ノンリピータブルリード３、ファントムリード）を認めるかどうかによって４つのレベルに分類することが可能。
↑
上記の基本概要も含めて、ISOLATION LEVELとは「**複数のトランザクションを並列に実行するにあたって、どのレベルではどのような問題が発生してしまうよって事」**を４つのレベルを用いて定義したものの事。
「トランザクションの隔離性水準はREAD UNCOMMITEDであるとする」と言われた場合、「ダーティリード、ノンリピータブルリード、ファントムリードが起きる可能性がある」と考える。そのほかも然り。
##4つのレベルとは？
ISOLATION LEVELは、４つのレベルに分類できる。以下４つのレベルを記述。一番下から上にかけて独立性阻害要因を許容する数が増える為レベルとしても上の方が低い設定になっている。

|名称|各レベルの説明|
|:-----------------:|:------------------:|
|READ UNCOMMITTED|最もレベルが低い。他のトランザクションで変更されたコミット前のデータを読み込んでしまうことがある。つまり、**ダーティリードが存在する。**|コミットが完了していない状態のデータ変更を許容してしまう事。このレベルでのSQL文は**ロックの考え方で言うと、共有ロックに該当する。**
|READ COMMITTED|コミットされたもののみ読み取る。つまり、コミットされたもののみしか読み取ることができない為**ダーティリードは防ぐことができる**|
|REPEATABLE READ|繰り返し同じデータを読み取っても、同じデータであることを保証する。つまり、あるトランザクションで読み取ったデータは、別のトランザクションで更新できなくなる為、**ノンリピータブルリードは防ぐことができる。**|
|SERIALIZABLE|複数のトランザクションをいくら実行させてもその影響を受けずに１つずつ実行したのと同じ結果を保証する。つまり、あるトランザクションが参照したテーブルは、追加、更新、消去のいずれもできなくなる。|

|ISOLATIONLEVEL\独立性阻害要因|Dirty read|Non-repeatable read|Phantom read|
|:------------------:|:------------------:|:------------------:|:------------------:
|READ UNCOMMITTED|○|○|○
|READ COMMITTED|✖︎|○|○
|REPEATABLE READ|✖︎|✖︎|○
|REPEATABLE READ|✖︎|✖︎|✖︎

最下段のSERIALIZABLEについては、最も直列実行可能性を保証した状態と言える。
###直列実行可能性とは？
例えば、トランザクション１（T1）とトランザクション２（T2）が存在した場合に、同時にT1とT2を実行した時、トランザクション実行の処理の流れがT1〜＞T2もしくは、T2〜＞T1といったように各トランザクションを個別に１つ実行してから次のトランザクションの実行に移るといったような動きをしているかどうかと言う事。トランザクションを並列で処理しているのにも関わらず、トランザクションを単体ずつで処理しているかのような処理形態かどうかの事。

##独立性阻害要因
###ダーティリード(dirty read)
他のトランザクションによって更新された”コミット前”のデータをあるトランザクションが読み込んでしまう事。その為、データの不整合が発生してしまう。
(ex)

|社員ID|社員名|所属部署名|
|:-----------------:|:------------------:|:------------------:|
|001|yamada|営業|
|002|sasaki|事務|
|003|saitou|会計|

上記のような関係”社員”が存在した場合に

```SQL:
INSERT INTO 社員 VALUES(004,"ueno",営業);
```
といったトランザクションT1のレコード挿入が起こり、

|社員ID|社員名|所属部署名|
|:-----------------:|:------------------:|:------------------:|
|001|yamada|営業|
|002|sasaki|事務|
|003|saitou|会計|
|004|ueno|営業|

上記のように関係”社員”が変更され、その後トランザクションT2が

```SQL:
SELECT * FROM 社員;
```
を実行し、結果が得られる。
その後、トランザクションT1で挿入された社員”ueno”のレコードを取り消す（ロールバック）が行われてしまった場合、トランザクションT２で得られた結果↓

|社員ID|社員名|所属部署名|
|:-----------------:|:------------------:|:------------------:|
|001|yamada|営業|
|002|sasaki|事務|
|003|saitou|会計|
|004|ueno|営業|

とトランザクションT1のロールバックが行われた後の結果↓

|社員ID|社員名|所属部署名|
|:-----------------:|:------------------:|:------------------:|
|001|yamada|営業|
|002|sasaki|事務|
|003|saitou|会計|

では、トランザクションT２で得られた結果にまだ消されたはずの"ueno"のレコードが存在するためそのまま処理が続いてしまう場合、整合性がけけてしまう。
この場合でいうと、トランザクションT2が”コミット前”のデータを読み込んでしまう事がダーティリードという事になる。

###ノンリピータブルリード（更新）
ノンリピータブルリードとは、同じデータを２回リードした時に値が異なる可能性のある読み方の事。１回目と２回目の間に別のトランザクションによりデータが変更され、不整合が発生する可能性がある。ファージリードともいう。
(ex)関係”社員”が合った場合↓

|社員ID|社員名|所属部署名|
|:-----------------:|:------------------:|:------------------:|
|001|yamada|営業|
|002|sasaki|事務|
|003|saitou|会計|

トランザクションT1が

```SQL:
SELECT * FROM 社員;
```
を実行し、関係”社員”テーブルを検索する。（この時点で、”社員名yamada”の所属部署名は”営業”となっている。）
次に、トランザクションT2で、

```SQL:
UPDATE 社員 SET 社員.所属部署名="会計" WHERE 社員.所属部署名＝”営業” ;
```

を実行して、関係”社員”のyamadaの所属部署名を”会計”に更新する。

|社員ID|社員名|所属部署名|
|:-----------------:|:------------------:|:------------------:|
|001|yamada|会計|
|002|sasaki|事務|
|003|saitou|会計|

その後、トランザクションT2が更新した事を確定する（コミットする）。
そして、再度、トランザクションT1が関係”社員”を検索すると、yamadaの所属部署名が”会計”として検索される。（この１回目と２回目で値が変わっている）事をノンリピータブルリードという。

###ファントムリード（追加、更新、消去）
１回目と２回目のリードの間に、他のトランザクションによってデータが追加されてしまう読み方の事。１回目にはなかった幻＝”ファントムなデータ”が発生して不整合になる可能性がある。
(ex)
トランザクションT1で、

```SQL:
INSERT 社員 INTO VALUES("004","gotou","人事");
```
を実行してレコードを挿入する。
トランザクションT2が関係”社員”を検索

```SQL:
SELECT * FROM 社員;
```
すると、まだトランザクションT1が未コミットな為”先ほど追加したレコード”は検索されない。下記状態。↓

|社員ID|社員名|所属部署名|
|:-----------------:|:------------------:|:------------------:|
|001|yamada|会計|
|002|sasaki|事務|
|003|saitou|会計|

トランザクションT1がコミットする。
その後、トランザクションT2が関係”社員”を検索すると、

|社員ID|社員名|所属部署名|
|:-----------------:|:------------------:|:------------------:|
|001|yamada|会計|
|002|sasaki|事務|
|003|saitou|会計|
|004|gotou|人事|

となっている為、（１回目にはなかったデータ）が出現している。

###ノンリピータブルリードとファントムリードの違い
ノンリピータブルリードは、前提として同じデータを読み込んでいるかどうかで判断する。ファントムリードは、１度目のリードで存在していなかったデータが２回目のリードで存在しているかどうかで判断を行う。