Closed9

MySQLにおけるデッドロックの調査方法

ikuma-tikuma-t

デッドロックの概要

デッドロックとは、それぞれが他の必要なロックを保持しているために、異なるトランザクションを続行できない状況です。 両方のトランザクションがリソースが使用可能になるのを待機しているため、保持しているロックは解放されません。

https://dev.mysql.com/doc/refman/8.0/ja/innodb-deadlocks.html

  • 互いにロックの解放待ちを行う場合に発生する。
  • デッドロックが発生するのは、ロックの待機を実施する排他ロックが1つでも含まれる場合
ikuma-tikuma-t

共有ロックと排他ロック

  • 共有ロック = sロック:読み取りを行なっているため、他からの更新を制限するロック
  • 排他ロック = xロック:更新中のため、他からの更新を制限するロック

共有ロックは複数のトランザクションが取得できるが、排他ロックは単一のトランザクションしか取得できない。

https://dev.mysql.com/doc/refman/8.0/ja/innodb-locking.html
https://zenn.dev/gibjapan/articles/1d8dfb7520dabc

ikuma-tikuma-t

共有ロックと排他ロックによるデッドロック

次のようなケースで発生する。

  1. トランザクションAが共有ロック取得
  2. トランザクションBが共有ロック取得
  3. トランザクションAが排他ロック取得(待機)
  4. トランザクションBが排他ロック取得(待機)

この時点でデッドロックが発生し、トランザクションBがロールバックされる(必ずトランザクションBなのか自信がない)

ikuma-tikuma-t

排他ロック同士のデッドロック

相手がロックを持っているリソースに対してそれぞれ排他ロックを取得すると、デッドロックが発生する。

ikuma-tikuma-t

ロックの範囲

いくつかあるみたいだけど、基本的にはテーブルロックと行ロック

ikuma-tikuma-t

インテンションロック

インテントロックは、トランザクションが後でテーブルの行に必要とするロックのタイプ (共有または排他) を示すテーブルレベルのロックです。 インテントロックには、次の 2 種類があります:
intention shared lock (IS) は、トランザクションがテーブルの個々の行に shared ロックを設定することを示します。
intention exclusive lock (IX) は、トランザクションがテーブル内の個々の行に排他ロックを設定することを示します。

https://dev.mysql.com/doc/refman/8.0/ja/innodb-locking.html#innodb-intention-locks

intent の意味の通りで、意図を示すためのロック。

SELECT ... FOR SHAREはISロックを、SELECT ... FOR UPDATEはIXロックを取得する。

意図的ロックでは、完全なテーブルリクエスト (LOCK TABLES ... WRITE など) 以外はブロックされません。 意図的ロックの主な目的は、誰かが行をロックしていること、またはテーブル内の行をロックしていることを示すことです。

あ〜、テーブルロックと行ロックで粒度が異なるけど、行ロックであっても「このテーブルに対してロックがかかっているらしい」という意図が伝わることで、テーブルロックが正しく動作できるようになるということか。

ikuma-tikuma-t

InnoDB におけるレコードロック

条件に合致した行に対するロックではなく、スキャンしたインデックスに対するロック。

レコードロックでは、テーブルにインデックスが定義されていなくても必ず、インデックスレコードがロックされます。 このような場合は、InnoDB によって非表示のクラスタ化されたインデックスが作成され、このインデックスを使用してレコードロックが行われます。

レポートでは次のように見えるそう。

RECORD LOCKS space id 58 page no 3 n bits 72 index `PRIMARY` of table `test`.`t`
trx id 10078 lock_mode X locks rec but not gap
Record lock, heap no 2 PHYSICAL RECORD: n_fields 3; compact format; info bits 0
 0: len 4; hex 8000000a; asc     ;;
 1: len 6; hex 00000000274f; asc     'O;;
 2: len 7; hex b60000019d0110; asc        ;;
ikuma-tikuma-t

ギャップロック

複数の範囲にかかるロック。

明示的に WHERE句で指定するのはわかりやすいが、注意したいのは存在しないレコードへの更新時、インデックスのはざますべてに対してロックがかかること。

このスクラップは2024/10/17にクローズされました