Skip to content

Instantly share code, notes, and snippets.

@etheriqa
Created March 12, 2013 19:22
Show Gist options
  • Star 4 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save etheriqa/5146101 to your computer and use it in GitHub Desktop.
Save etheriqa/5146101 to your computer and use it in GitHub Desktop.
[InnoDB] 非ユニークキーによる行ロックの範囲についてちょっと調べた

[InnoDB] 非ユニークキーによる行ロックの範囲についてちょっと調べた

バージョン

% mysql --version
mysql  Ver 14.14 Distrib 5.5.29, for debian-linux-gnu (x86_64) using readline 6.2

調査方法

  1. CREATE TABLE innodb_lock_monitor(a int) ENGINE=InnoDB
  2. BEGIN
  3. ロックを獲得するクエリを実行
  4. SHOW ENGINE INNODB STATUSTRANSACTIONSを読む
  5. ROLLBACK
    1. に戻ってクエリ実行を繰り返す

利用したテーブル

mysql> SHOW CREATE TABLE t\G
*************************** 1. row ***************************
       Table: t
Create Table: CREATE TABLE `t` (
  `a` int(11) NOT NULL,
  `b` int(11) NOT NULL AUTO_INCREMENT,
  PRIMARY KEY (`b`),
  KEY `a` (`a`)
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=latin1

mysql> SELECT * FROM t;
+-----+---+
| a   | b |
+-----+---+
|  16 | 1 |
|  32 | 2 |
|  48 | 3 |
|  64 | 4 |
|  80 | 5 |
+-----+---+

結果

ALL

(おそらく主キーの全ノードに対してネクストキーロックがかかりそう)

index

  1. SELECT * FROM t FOR UPDATE
    • a の 16, 32, 48, 64, 80, sup にネクストキーロック
    • PRIMARY の 1, 2, 3, 4, 5 にレコードロック

range (ASC)

  1. SELECT * FROM t WHERE a IN (16, 32) FOR UPDATE
    • a の 16, 32 にレコードロック
    • PRIMARY の 1, 2 にレコードロック
  2. SELECT * FROM t WHERE a < 48 FOR UPDATE
    • a の 16, 32, 48 にネクストキーロック
    • PRIMARY の 1, 2, 3 にレコードロック
  3. SELECT * FROM t WHERE a <= 48 FOR UPDATE
    • a の 16, 32, 48, 64 にネクストキーロック
    • PRIMARY の 1, 2, 3, 4 にレコードロック
  4. SELECT * FROM t WHERE a >= 48 FOR UPDATE
    • a の 48 にレコードロック
    • a の 64, 80, sup にネクストキーロック
    • PRIMARY の 3, 4, 5 にレコードロック
  5. SELECT * FROM t WHERE a > 48 FOR UPDATE
    • a の 64, 80, sup にネクストキーロック
    • PRIMARY の 1, 2, 3 にレコードロック

range (DESC)

  1. SELECT * FROM t WHERE a < 32 ORDER BY a DESC FOR UPDATE
    • a の 16 にネクストキーロック
    • a の 32 の直前にギャップロック
    • PRIMARY の 1 にレコードロック
  2. SELECT * FROM t WHERE a <= 32 ORDER BY a DESC FOR UPDATE
    • a の 16, 32 にネクストキーロック
    • a の 48 の直前にギャップロック
    • PRIMARY の 1, 2 にレコードロック
  3. SELECT * FROM t WHERE a >= 64 ORDER BY a DESC FOR UPDATE
    • a の 48, 64, 80, sup にネクストキーロック
    • PRIMARY の 3, 4, 5 にレコードロック
  4. SELECT * FROM t WHERE a > 64 ORDER BY a DESC FOR UPDATE
    • a の 64, 80, sup にネクストキーロック
    • PRIMARY の 4, 5 にレコードロック

ref

  1. SELECT * FROM t WHERE a = 16 FOR UPDATE
    • a の 16 にネクストキーロック
    • a の 32 の直前にギャップロック
    • PRIMARY の 1 にレコードロック
  2. SELECT * FROM t WHERE a = 0 FOR UPDATE
    • a の 16 の直前にギャップロック
  3. SELECT * FROM t WHERE a = 20 FOR UPDATE
    • a の 32 の直前にギャップロック
  4. SELECT * FROM t WHERE a = 100 FOR UPDATE
    • a の sup にネクストキーロック

eq_ref

(ユニークキーによる行ロックのみ)

const

(ユニークキーによる行ロックのみ)

  1. SELECT * FROM t WHERE b = 1 FOR UPDATE
    • PRIMARY の 1 にレコードロック

さらに調べないといけなそうなこと

  • 複合キー
  • LIMIT
  • JOIN
  • サブクエリ

参考文献

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment