データベースのトランザクションとロックについて

# トランザクションとは
***複数のSQL文を１つにまとめてDBに反映できます。***


例えば下の４つの命令文をまとめて処理できます。

```sql
SELECT
INSERT
UPDATE 
DELETE 
```

トランザクションに書き直して見ていきます。

⚫︎補足
DBはデータベースの略

# トランザクションの書き方

⚫︎***BEGINとCOMMIT***

```sql
BEGIN  --開始の指示

SELECT
INSERT
UPDATE 
DELETE

COMMIT  --終了の指示　   -- 変更を反映
```
BEGINとCOMMITの間に文を挟んで反映させます。
```BEGINは開始の指示```で```COMMITは終了の指示で変更を反映```させます。

⚫︎***BEGINとROLLBACK***

```sql
BEGIN  --開始の指示

SELECT
INSERT
UPDATE 
DELETE

ROLLBACK  --終了の指示　   -- 取り消しを反映
```
BEGINとROLLBACKの間に文を挟んで反映させます。
```BEGINは開始の指示```で```ROLLBACKは終了の指示　で取り消しを反映```させます。



⚫︎注意
***一度COMMITすると後からROLLBACKはできないです。***

# なぜトランザクションを使うのか

***Amazonの購入処理を例に***出します。

1***在庫テーブルのUPDATE***(商品を購入して更新)
2***クレジットカードで決済処理***(API)
3***購入履歴のINSERT***(購入履歴の追加)

⚫︎***トランザクションがない場合***
在庫テーブルから在庫を購入してカードで決済したにもかかわらず
在庫が減ってしまう現象が起きます。
こういうことがないように処理を一つにまとめて処理します。

⚫︎***トランザクションがある場合***
ある場合を見ていきます。

```
BEGIN(開始)

1在庫テーブルのUPDATE(商品を購入して更新)
2クレジットカードで決済処理(API)　　  失敗
3購入履歴のINSERT(購入履歴の追加)

ROLLBACKで反映が取り消し
```

決済が失敗したとしてもROLLBACKを反映させると処理が取り消されて
在庫が減ったりすることがなくなります。


```
BEGIN(開始)

1在庫テーブルのUPDATE(商品を購入して更新)
2クレジットカードで決済処理(API)　　 失敗
3購入履歴のINSERT(購入履歴の追加)

COMMITで反映が確定
```

処理に問題がない場合は一括で一連の処理を反映できます。

# トランザクションを使うケース
どう言う時に使うのか。

1. 手動でSQLを操作する時に誤ってお客さんのデータが消えてしまわないように対策します。

2.複数のデータやレコードをまとめたい時に使います。


# ロック
***ロック***とい****複数のユーザーが同時に更新しても
反映がおかしくならないようにするための仕組み***です。

# ロックの種類
ロックの種類を説明します。

⚫︎```共有ロック(READロック)```
***他のユーザーのSELECTだけ認め、DELETEやUPDATEのデータ変更の命令文は認めません。***

・```SELECT FOR UPDATE ```
***行単位で共有ロックをかけるSQL文***

・注意点
1.トランザクションの中で使う
2.処理が終わったらCOMMIT、ROLLBACKをする
3.beginしたらSELECT FOR UPDATE を使う　(これをやらないと***デットロックに***)
4.独特な行指定できる条件を使うこと

・補足
***デットロック***とは***永遠にロックが開放されない***ことです。

⚫︎```占有ロック(WRITEロック)```
***他のユーザーの処理を一切認めないことです。***

⚫︎```テーブルロック```
***対象のテーブル全体にロックがかかる***。

⚫︎```行(=レコード)ロック```
***対象のレコードのみにロックがかかる***

⚫︎```アドバイザリロック```
***名前を指定してロックをかける***
結構便利みたいです!

⚫︎```楽観的ロック```
***更新直前にロックをかける***
最近は使わないみたいです。

⚫︎```悲観的ロック```
***最初にロックをかける***


# デットロックとは
***データベースで同時にトランザクションが実行されることにより
複数ユーザーがお互いにロックが開放されるのを待って永遠に
ロックが開放されないこと***です。

# デットロックの予防
デットロックの予防法は以下の2点みたいです。

⚫︎対策1 トランザクションの時間を短くする

⚫︎対策2 同じ順番でロックをする

・多数の行ロックがかけられ自動的に表ロックなどに切り替わる```ロックエスカレーション```がある。
・```2フェーズコミット```という***各データベースにトランザクションの「確定準備」と「確定」の
2段階で指示を出し整合性を保ちます***。

⚫︎対策3 更新順とテーブルの更新順を守る

⚫︎対策4 アドバイザリロックを使う

# デットロックの解消法
***ロックを終了することです。***
なかなか解消が難しいのでこの方法を使うみたいです。

# ギャップロック
***存在しないレコードにロックがかかり隙間の行にロックがかかること***です。

ex)下のIDのデータがあるとします。
SELECT FOR UPDATE を使い8を指定すると８がロック。
もし11みたいに存在しないIDにロックがかかると11〜14までロックがかかります。
7にロックをかけると1~7までロックがかかり、１６にかけると１６以降全部のデータにロックがかかります。

ID
  8 10  15 

⚫︎注意
***ギャップロックは他人のSELECT FOR UPDATEを許してしまうリスク***があります。




# 最後に
説明が足りない部分があるので今後も更新していきます。
下記の動画は非常にわかりやすいので良かったら見てみてください。



⚫︎参考資料
https://qiita.com/zd6ir7/items/6568b6c3efc5d6a13865

https://www.amazon.co.jp/%E3%82%B9%E3%83%83%E3%82%AD%E3%83%AA%E3%82%8F%E3%81%8B%E3%82%8BSQL%E5%85%A5%E9%96%80-%E7%AC%AC2%E7%89%88-%E3%83%89%E3%83%AA%E3%83%AB222%E5%95%8F%E4%BB%98%E3%81%8D-%E3%82%B9%E3%83%83%E3%82%AD%E3%83%AA%E3%82%B7%E3%83%AA%E3%83%BC%E3%82%BA-%E4%B8%AD%E5%B1%B1%E6%B8%85%E5%96%AC/dp/4295005096


⚫︎参考動画

https://m.youtube.com/watch?v=d3FRYLfGT6A&list=PL-1KBX2gDRujQaRgEByueezHBiqHP8KDD&index=5


https://m.youtube.com/watch?v=oV3VhDu9QHc&list=PL-1KBX2gDRujQaRgEByueezHBiqHP8KDD&index=6

https://m.youtube.com/watch?v=3tMC5KkLY4Q&list=PL-1KBX2gDRujQaRgEByueezHBiqHP8KDD&index=7