トランザクション分離レベルの勉強記録(3) innodb_lock_monitorのTRANSACTIONS部分の読み方

[前回](http://qiita.com/noonworks/items/3c813e3f8c8089644246)のまとめ。

* `innodb_lock_monitor`を使えば、ロックのタイプごとにモードや詳細モード、範囲が確認できる
* あるトランザクションにおいて、読み取り時にどのバージョンが参照されるかもわかる
* 出力内容の読み方についてのドキュメントがないので、他のドキュメントから推測したりソースを読んだりした


## 読み方

```text
(1) // ---TRANSACTION 31826445, ACTIVE 627 sec
    // 2 lock struct(s), heap size 320, 1 row lock(s)
    // MySQL thread id 4, OS thread handle 0x7ac, query id 18 localhost ::1 root cleaning up
(2) // Trx read view will not see trx with id >= 31826446, sees < 31826443
(3) // TABLE LOCK table `til`.`test` trx id 31826445 lock mode IS
(4) // RECORD LOCKS space id 42733 page no 3 n bits 72 index `PRIMARY` of table `til`.`test` trx id 31826445 lock mode S
(5) // Record lock, heap no 2 PHYSICAL RECORD: n_fields 4; compact format; info bits 0
(6) //  0: len 4; hex 80000001; asc     ;;
(6) //  1: len 6; hex 000001e5a00b; asc       ;;
(6) //  2: len 7; hex 8b000001750110; asc     u  ;;
(6) //  3: len 4; hex 8000000a; asc     ;;
```

* (1)トランザクションごとに`---TRANSACTION ...`で区切られる。`TRANSACTION`の後にある数字が**トランザクションID**。
* (2)このトランザクションがどのバージョンを読み取るか。トランザクションIDで表示されている。どの範囲になるかはトランザクション分離レベルによって異なるはず。
* (3)テーブルロックの情報。**ロックのモード**が表示される。
* (4)行ロックの情報。**ロックの精密なモード**（レコードロック、ギャップロック、ネクストキーロック）が表示される。
* (5)ロックされたレコードの情報。レコード1行ごとに出力される。`n_fields`の数ぶんの(6)を持つ。
* (6)フィールドの情報。フィールド1つごとに出力される。
  - 実際のフィールドに加えて**トランザクションID**と**ロールポインタ**の行が追加される
  - 表示される内容は`通し番号: len 長さ; hex 16進データ; asc ascii表示; 表示時の省略情報; externalデータ;`
* (6)に表示されるフィールドの順番
  1. 主キーのフィールド
     * プライマリキーか、なければNOT NULLのUNIQUEインデックス
     * 該当するインデックスが複合キーの場合、**インデックスの順番で表示**
     * プライマリキーもNOT NULLのUNIQUEキーもない場合、6バイトの**行ID**が自動で追加される
  2. **トランザクションID**（6バイト）：最後にこの行を更新したトランザクションのIDが格納されている
  3. **ロールポインタ**（7バイト）：Undoログの場所を指しているらしい
  4. それ以外のフィールド（定義順）
* （たぶんクラスタインデックスの物理構成そのまま）


## 出力と出力している関数の対応

```
   +------------ // ------------
   |             // TRANSACTIONS
(1)|             // ------------
   |             // Trx id counter 31826446
   |             // Purge done for trx's n:o < 31825964 undo n:o < 0 state: running but idle
   +------------ // History list length 431
   +------------ // LIST OF TRANSACTIONS FOR EACH SESSION:
   |       +---- // ---TRANSACTION 31826445, ACTIVE 627 sec
   |    (3)|     // 2 lock struct(s), heap size 320, 1 row lock(s)
   |       +-(4) // MySQL thread id 4, OS thread handle 0x7ac, query id 18 localhost ::1 root cleaning up
   |             // Trx read view will not see trx with id >= 31826446, sees < 31826443
   |         (5) // TABLE LOCK table `til`.`test` trx id 31826445 lock mode IS
   |   +-------- // RECORD LOCKS space id 42733 page no 3 n bits 72 index `PRIMARY` of table `til`.`test` trx id 31826445 lock mode S
   |   |     (7) // Record lock, heap no 2 PHYSICAL RECORD: n_fields 4; compact format; info bits 0
   |(6)|   +-(9) //  0: len 4; hex 80000001; asc     ;;
   |   |(8)| (9) //  1: len 6; hex 000001e5a00b; asc       ;;
   |   |   | (9) //  2: len 7; hex 8b000001750110; asc     u  ;;
(2)|   +---+-(9) //  3: len 4; hex 8000000a; asc     ;;
   |             //
   |       +---- // ---TRANSACTION 31826444, ACTIVE 2361 sec
   |    (3)|     // 2 lock struct(s), heap size 320, 1 row lock(s), undo log entries 1
   |       +-(4) // MySQL thread id 3, OS thread handle 0x1044, query id 10 localhost ::1 root cleaning up
   |         (5) // TABLE LOCK table `til`.`test` trx id 31826444 lock mode IX
   |   +-------- // RECORD LOCKS space id 42733 page no 3 n bits 72 index `PRIMARY` of table `til`.`test` trx id 31826444 lock_mode X locks rec but not gap
   |   |     (7) // Record lock, heap no 3 PHYSICAL RECORD: n_fields 4; compact format; info bits 0
   |(6)|   +-(9) //  0: len 4; hex 80000002; asc     ;;
   |   |(8)| (9) //  1: len 6; hex 000001e5a20c; asc       ;;
   |   |   | (9) //  2: len 7; hex 0c00000fd0062f; asc       /;;
   |   +---+-(9) //  3: len 4; hex 800000dc; asc     ;;
   |             //
   |    (3)+---- // ---TRANSACTION 31826443, ACTIVE 2758 sec
   |       +-(4) // MySQL thread id 1, OS thread handle 0x954, query id 12 localhost ::1 root cleaning up
   +------------ // Trx read view will not see trx with id >= 31826444, sees < 31826444
```

1. [lock_print_info_summary](https://github.com/mysql/mysql-server/blob/3a4e7bc7c416888fda897239c03549c2929bb64c/storage/innobase/lock/lock0lock.cc#L5149)
2. [lock_print_info_all_transactions](https://github.com/mysql/mysql-server/blob/3a4e7bc7c416888fda897239c03549c2929bb64c/storage/innobase/lock/lock0lock.cc#L5238)
3. [trx_print_low](https://github.com/mysql/mysql-server/blob/3a4e7bc7c416888fda897239c03549c2929bb64c/storage/innobase/trx/trx0trx.cc#L1702)
4. [thd_security_context](https://github.com/mysql/mysql-server/blob/23032807537d8dd8ee4ec1c4d40f0633cd4e12f9/sql/sql_class.cc#L899)
5. [lock_table_print](https://github.com/mysql/mysql-server/blob/3a4e7bc7c416888fda897239c03549c2929bb64c/storage/innobase/lock/lock0lock.cc#L4978)
6. [lock_rec_print](https://github.com/mysql/mysql-server/blob/3a4e7bc7c416888fda897239c03549c2929bb64c/storage/innobase/lock/lock0lock.cc#L5017)
7. [rec_print_new](https://github.com/mysql/mysql-server/blob/3a4e7bc7c416888fda897239c03549c2929bb64c/storage/innobase/rem/rem0rec.cc#L1870)
8. [rec_print_comp](https://github.com/mysql/mysql-server/blob/3a4e7bc7c416888fda897239c03549c2929bb64c/storage/innobase/rem/rem0rec.cc#L1825)
9. [ut_print_buf](https://github.com/mysql/mysql-server/blob/3a4e7bc7c416888fda897239c03549c2929bb64c/storage/innobase/ut/ut0ut.cc#L425)


## 今回の感想

ソースを読もう！


## 次回の予定

トランザクション分離レベルごとに`innodb_lock_monitor`を読む。


## 追記（2017/05/11）

[InnoDBのロックに関する用語の確認](http://qiita.com/noonworks/items/e7c17c91caab1bbb7593)に合わせて用語を修正。