インデックス ロックの怖い話1
身に憶えのないDeadlock found when trying to get lock
https://bugs.mysql.com/bug.php?id=69835
https://bugs.mysql.com/bug.php?id=43210
https://bugs.mysql.com/bug.php?id=43591
Next Illuminate\Database\QueryException: SQLSTATE[40001]: Serialization failure: 1213 Deadlock found when trying to get lock; try restarting transaction (SQL: update items
set error_message = concat(ifNull(items.error_message, ""),
{"type":"2","key":"","replacement":[]})
update 時のロック
(特定レコードへの処理)
Aの処理
Bの処理
Cの処理
↓
A:処理中
B:待機
C:待機
↓
A:完了
B:処理中
C:エラー(デッドロックエラー)
こんな感じで、ウェイトが2つ以上ある場合、2つ目以降は全てエラーとして扱われるらしい。
「デッドロック」と銘打っているものの、ロック扱いとなっていない?
insert 時のロック
同時に insert が走ると、デッドロックが走る事がある。
(id を予約して insert するため)
A:insert 処理1
B:insert 処理2
C:insert 処理3
↓
A:処理中
B:待機
C:待機
↓
A:完了
B:処理中
C:エラー(デッドロックエラー)
<対策>
リトライする
直列にする
repeatable read の設定を変える
Exception で検知はできる
(トランザクションの分離レベルが「repeatable read」) ※デフォルト
トランザクション分離レベル
https://qiita.com/song_ss/items/38e514b05e9dabae3bdb
https://techracho.bpsinc.jp/kotetsu75/2018_12_14/66410
http://bashalog.c-brains.jp/18/04/17-130000.php
データベースでは以上のような問題を防ぐための設定が用意されています。
トランザクションの独立性と処理速度はトレードオフになるので、 そのバランスをどうするかを、トランザクションの分離レベルで設定できる。
トランザクション分離レベルにはREAD UNCOMMITED, READ COMMITED, REPEATABLE READ, SERIALIZABLEの4つの段階があります。 READ UNCOMMITEDが最も分離レベルが低く、SERIALIZABLEが一番高い。