気軽に楽しくプログラムと遊ぶ

自分が興味があってためになるかもって思う情報を提供しています。

MySQL ギャップロックとは?

現場でギャップロックという聞き慣れない用語を耳にしたので、

以下の記事を参考に理解する。

MySQLのギャップロックとネクストキーロック - 41から始めました

MySQLロック

ロックの種類

  • 排他ロック
  • 共有ロック
    • 排他ロックがかかったデータを参照する際にかかるロック
    • ロックを保持するトランザクションによる行の読み取りが許可、書き込み不可
    • 共有ロック中データに対して、他トランザクションでも共有ロックは可能。そういう意味で共有ロック

ロック中データ(行)の扱い

InnoDBトランザクション分離レベルによって、ロック中の行の書き込み不可や読み取り不可などにできる。
MySQLInnoDBのデフォルト分離レベルはREPEATABLE READで、ロック中の行の書き込み不可かつ、読み取りは可能な状態になっている。

トランザクション分離レベル

下に行くほど分離レベルが高い

分離レベル 説明 デフォルト設定採用のDMBS
READ UNCOMMITTED コミットされていない変更を他のトランザクションから参照可 -
READ COMMITTED コミットされた変更を他のトランザクションから参照可 OraclePostgreSQLSQL Server
REPEATABEL READ コミットされ、トランザクション終了後の変更を他のトランザクションから参照可 MySQL
SERIALIZABLE 強制的にトランザクションを順序付けて処理。 -

ギャップロックとは?

InnoDBには3種類のロックがあります。

  • レコードロック:単一レコードのロック
  • ギャップロック:各種ギャップに対するロック
  • ネクスキーロック:レコードロックとそのレコードの直前のギャップロックの組み合わせ

ギャップロックのギャップは以下の三つで、MySQLでは対象レコードと以下のギャップにあるレコードにロックがかかります。

  • index値を持つ行と行の間にあるギャップ
    • レコードIDが1、3をロックしたときにID=2(間のギャップ)へのレコード挿入がロック待ちとなる
  • 先頭のindex値を持つ行の前のギャップ
    • レコードIDが4、5をロックしたとき、ID=3(先頭のギャップ)へのレコード挿入がロック待ちとなる。ID=2なら挿入可
  • 末尾のindex値を持つ行の後のギャップ
    • レコードIDが4、5をロックしたとき、ID=6(末尾のギャップ)へのレコード挿入がロック待ちとなる。ID=7なら挿入可

MySQLでデットロックや更新タイムアウトが発生した際に、ギャップロックを思い出すと問題解決になるかもしれない。