PageとRecord (2)
今朝はrow_format=redundantの時にold styleであることの当たりをつけたので、今度はrow_format=compactで作成したテーブルのhexdumpを解析しませう。
DDLおよびDMLは以下。row_format=compactはデフォルト値なので別に付与しなくとも良いけど気分的に。
create table t_compact ( c1 int primary key, c2 char(10) charset latin1 ) engine = innodb row_format = compact; insert into t_compact values (1, '1111'), (2, '2222'), (16, '3333'), (8, '4444');
dumpデータはこちら:http://ikda.net/resource/mysql/ibdata1_hd2
該当Pageのhexdumpは以下。HEXのパターンからなんとなくで各レコード(と思われる範囲)に色をつけてみた。
000cfff0 00 00 00 00 00 74 00 65 75 4e 3f 5d 00 00 fa 99 |.....t.euN?]...| 000d0000 df c5 80 64 00 00 00 34 ff ff ff ff ff ff ff ff |.d...4| 000d0010 00 00 00 00 00 01 21 4b 45 bf 00 00 00 00 00 00 |......!KE......| 000d0020 00 00 00 00 00 00 00 02 00 fc 80 06 00 00 00 00 |...............| 000d0030 00 e1 00 05 00 00 00 04 00 00 00 00 00 00 00 00 |...............| 000d0040 00 00 00 00 00 00 00 00 00 1a 00 00 00 00 00 00 |................| 000d0050 00 02 15 f2 00 00 00 00 00 00 00 02 15 32 01 00 |............2..| 000d0060 02 00 1b 69 6e 66 69 6d 75 6d 00 05 00 0b 00 00 |...infimum......| 000d0070 73 75 70 72 65 6d 75 6d 00 00 00 10 00 21 80 00 |supremum.....!..| 000d0080 00 01 00 00 00 00 19 06 80 00 00 00 2d 01 10 61 |............-..a| 000d0090 61 61 61 20 20 20 20 20 20 00 00 00 18 00 42 80 |aaa .....B.| 000d00a0 00 00 02 00 00 00 00 19 06 80 00 00 00 2d 01 1c |.............-..| 000d00b0 62 62 62 62 20 20 20 20 20 20 00 00 00 20 ff b0 |bbbb ... | 000d00c0 80 00 00 10 00 00 00 00 19 06 80 00 00 00 2d 01 |..............-.| 000d00d0 28 63 63 63 63 20 20 20 20 20 20 00 00 00 28 ff |(cccc ...(| 000d00e0 df 80 00 00 08 00 00 00 00 19 06 80 00 00 00 2d |..............-| 000d00f0 01 34 64 64 64 64 20 20 20 20 20 20 00 00 00 00 |.4dddd ....| 000d0100 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
ちょっとこの部分に絞って見てみよう。
000d0090 61 61 61 20 20 20 20 20 20 00 00 00 18 00 42 80 |aaa .....B.| 000d00a0 00 00 02 00 00 00 00 19 06 80 00 00 00 2d 01 1c |.............-..| 000d00b0 62 62 62 62 20 20 20 20 20 20 00 00 00 20 ff b0 |bbbb ... |
経験的にパッと分かるのは、0x000d009fから0x000d00a3にかけての"80 00 00 02"が主キーの値であるc1=2、次の6バイト分"00 00 00 00 19 06"がトランザクションID、その次の7バイト分"80 00 00 00 2d 01 1c"がロールポインタ、そこから先がc2="bbbb"ということ。
しかしさて、こうなるとちょっと困ってしまった。
00 00 00 18 00 42
Record Headerと呼べる部分がこれしか無いことになる。
ちょっと並べてみよう。
c1=1 00 00 00 10 00 21 c1=2 00 00 00 18 00 42 c1=16 00 00 00 20 ff b0 c1=8 00 00 00 28 ff df
まずは逆順先頭2バイトが持っているPage内での相対ポインタに注目。
少しかじった知識によると、このPage内のレコードのポインタは以下の順序で次のレコードを指している。
infimum → c1=1 → c1=2 → c1=8 → c1=16 → supremum
でもって相対ポインタなので、、、
- c1=1の"00 21"は次のレコードの相対位置が+33であることを意味
- c1=2の"00 42"は次のレコードの相対位置が+66であることを意味
- c1=16の"ff b0"は次のレコードの相対位置が-80であることを意味
- c1=8の"ff df"は次のレコードの相対位置が-33であることを意味
というわけで、これを元にhexdumpを見直してみると、ちゃんと予想した通りのdumpになっている。
問題はグレー以外の残りの部分。どうみてもRecord Offset情報は記述されていない。
c1=1 00 00 00 10 00 21 c1=2 00 00 00 18 00 42 c1=16 00 00 00 20 ff b0 c1=8 00 00 00 28 ff df
次のbyteの下位3bitがレコードの種類なのだけれども、
0x10 = 0001 0000 0x18 = 0001 1000 0x20 = 0010 0000 0x28 = 0010 1000
ということで、4つとも"000"であり、Record Typeは"Conventional"ということになる。これも筋が通る。
ちなみにsupremumレコードのRecord Typeは0x0bの下位3bitということで"0000 1011"により"011"であり、rem0rec.cのコメント通りsupremum型となっている。
infimumレコードも0x02の下位3bitということで"010"となることからinfimum型である。
ついでにsupremumの相対ポインタの値は"00 00"、infinumの相対ポインタの値は"00 1b"(+27)ということでバッチリだ。
次は13bitで表現されたindex page内のheapにおけるレコード番号というものなのだけれども、ちょっと整理。青が相対ポインタ、緑がレコード型、橙がレコード番号。
infinum = 32 01 00 02 00 1b = 0011 0010 0000 0001 0000 0000 0000 0010 0000 0000 0001 1011 supremum = 00 05 00 0b 00 00 = 0000 0000 0000 0101 0000 0000 0000 1011 0000 0000 0000 0000 c1=1 = 00 00 00 10 00 21 = 0000 0000 0000 0000 0000 0000 0001 0000 0000 0000 0010 0001 c1=2 = 00 00 00 18 00 42 = 0000 0000 0000 0000 0000 0000 0001 1000 0000 0000 0100 0010 c1=16 = 00 00 00 20 ff b0 = 0000 0000 0000 0000 0000 0000 0010 0000 1111 1111 1011 0000 c1=8 = 00 00 00 28 ff df = 0000 0000 0000 0000 0000 0000 0010 1000 1111 1111 1110 1111
この13bitは単純にPage内でのレコード番号を意味しており、、というかこの場所自身がIndex PageのHeapってことなんかな。INSERTされた順序とかで付与されるっぽい。
続いて赤色の部分が、recordのn_owned。infinumとsuprenumには1とか5とか付いてるけど、普通のレコードには今のところついていない。
続いて灰色の部分が、deleteされたかどうかのマーク。とりあえずどれも生きてるから0らしい。次はdeleteしてみてhexdumpを確認してみるか。GCされる前にやらんと見えないと思うけど。
最後は黒の部分。ソースコメントによれば、
SQL-null flags (1 bit per nullable field), padded to full bytes
ということで値がNULLの場合にはbitが立つとか。複数カラムあったらどうすんだ?とか今のところ意味不明。infinumだけなんか値入ってるし。
ソースコメントによれば最後の最後、
length of the last non-null variable-length field of data: |
length of first variable-length field of data |