LoginSignup
4
3

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

Last updated at Posted at 2022-01-20

トランザクションとは

複数のSQL文を1つにまとめてDBに反映できます。

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

SELECT
INSERT
UPDATE 
DELETE 

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

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

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

⚫︎BEGINとCOMMIT

BEGIN  --開始の指示

SELECT
INSERT
UPDATE 
DELETE

COMMIT  --終了の指示    -- 変更を反映

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

⚫︎BEGINとROLLBACK

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を指定すると8がロック。
もし11みたいに存在しないIDにロックがかかると11〜14までロックがかかります。
7にロックをかけると1~7までロックがかかり、16にかけると16以降全部のデータにロックがかかります。

ID
8 10 15

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

最後に

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

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

⚫︎参考動画

4
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
3