これは何?
業務でデッドロックが発生。そもそもデッドロックはどのような場合に発生して、どのような対応が適切なのか?について理解が曖昧だと感じたので改めて調べてまとめた。
前提
Tips
デッドロックとはなにか?
A deadlock is a situation where different transactions are unable to proceed because each holds a lock that the other needs. Because both transactions are waiting for a resource to become available, neither ever release the locks it holds.
MySQLのリファレンスには上記のように記載されています。 「トランザクションごとにロックを専有し、トランザクション同士が互いにロックの開放を待つ状態になってしまうことでトランザクションの処理が続行できなくなること」がInnoDBにおけるトランザクションの定義でしょうか。 余談ですが、トランザクションの挙動はRDBMSによって仕様が変わるので注意してみていきたいところ。
デッドロックはどうやって発生するのか?
MySQL :: MySQL 8.0 リファレンスマニュアル :: 15.7.5.1 InnoDB デッドロックの例
デッドロックの対処方法は?
- 公式リファレンスに記載がありました(親切)
その中でもひとまずここは見ておく・改善すべきかなという点を個人の独断と偏見でピックアップしました。
SHOW ENGINE INNODB STATUS
コマンドを実行して原因を特定する- データを挿入または更新するトランザクションのサイズを小さくする。
- トランザクションを再試行する。
- トランザクションを一貫性のある順序で実行する。
その他の対処方法や詳細はこちら MySQL :: MySQL 8.0 リファレンスマニュアル :: 15.7.5.3 デッドロックを最小化および処理する方法
今回はどんな事象が発生した?
後ほど更新
事象に対する仮説
InnoDB では自動行レベルロックが使用されます。 単一の行を挿入または削除するだけのトランザクションの場合でも、デッドロックが発生する可能性があります。 その原因は、これらの操作が実際には「原子的」でないためです。これらの操作では自動的に、挿入または削除される行のインデックスレコード (複数の可能性あり) にロックが設定されます。
- InnoDBでは、
自動行レベルロック
が使用されている点。 - 自分の理解では行ロックとは、複数のトランザクション処理が同一のレコードに対して行われる際に発生すると考えていた。
- 実際には範囲ロックとネクストキーロックが絡んでいると思われる
感想
- デッドロックが分離レベルとは関係がないという点が自分の理解が曖昧で、当初の調査で際にそのあたりも関係があるのではないか?と調べてしまっていました。普通に考えれば「それはそう」という感じだったんですが、理解があやふやなままいると、いざ不具合に直面した際にあらぬ方向へ進んでしまい時間を無駄にしてしまうので、知識のインプットや知識の整理は仕事の効率を上げるうえでも非常に重要だなと改めて感じました。 また、参考記事にあげているようなわかりやすい記事を書いていただいている皆様には感謝の念しかありません。