innodbのレコードの構造

レコードのフォーマットはrem0rec.cに詳しい説明がある。
OLD STYLEとNEW STYLEの2種類がある。
(MySQL Internals Manualの説明はOLD STYLEのもの)

index->table->compが1だとNEW STYLE。
compはdict_mem_table_create()で設定している。
ha_innobase::create -> create_table_def -> dict_mem_table_create

create tableで、row_format=redundantのとき、compがFALSEになる。
それ以外(default, compressedなど)のときは、compはTRUEになる。
指定しなかったときもTRUEになる。
システムカタログ(SYS_TABLESなど)は、comp = FALSE。

MySQL 5.0.3 Release Notes
---------------------------------------------------------------------
InnoDB: Introduced a compact record format that does not store
the number of columns or the lengths of fixed-size columns.
The old format can be requested by specifying ROW_FORMAT=REDUNDANT.
The new format (ROW_FORMAT=COMPACT) is the default. 
---------------------------------------------------------------------

OLD_STYLEのRecord Format

Record Formatは、大きくわけて3つのデータからなる。
(1)データへのオフセットリスト
最終フィールドから順に設定される。
(2)レコードの情報 (6bytes)
各種フラグや次のレコードへのポインタなど、レコードの情報が格納される。
(3)データ
データリスト。各フィールドのデータは、オフセットリストで指定された位置に存在する。

レコードの先頭アドレス(Origin of the record)は、データリストの先頭位置が使用される。オフセットリストに指定されるオフセットは、これが基点になるので、先頭フィールドのオフセットは0。

以下のようなレイアウトになる。

 最終フィールドのデータ末尾のoffset
 ......
 2番目のフィールドのデータ末尾のoffset
 先頭フィールドのデータ末尾のoffset
 レコード情報(6 bytes)
                        <---- ここがOrigin of the recordのポインタ
 先頭フィールドのデータ
 2番目のフィールドのデータ
 ......
 最終フィールドのデータ

オフセットについて:オフセットの先頭ビットはNULLフラグとして使用される。レコード長(データの長さの合計値)が127byte未満のときは、各フィールドのオフセットは1byteで表現される。それ以上のときは2byte使う。オフセット長が1byteか2byteかどうかは、レコード情報のフラグに設定される。
また、2byteのときは、2番目のビットはデータが別ページに保存されたことを示すフラグとして使用される。
オフセットには各フィールドの末尾の位置が設定されるので、あるフィールドの先頭のオフセットを知りたいときは、1つ前のフィールドのオフセットを見る。

レコード情報のレイアウトは以下のとおり。

 未使用 (2 bits)
 削除フラグ (1 bit)
 min_rec_flag (1 bit)
 このレコードが保持しているレコード数 (4 bits)
 レコード番号 (13 bits)
 フィールドの数 (10 bits)
 1byteオフセットフラグ (1 bit)  1だったらオフセットは1byte。0だったら2byte。
 次のレコードへのポインタ (16 bits)

NEW_STYLEのRecord Format

NEW_STYLEはレコードサイズが小さくなるように、以下の工夫をしている
(1)各レコードにフィールド数をもたない
(2)オフセットではなく、データ長をもつ
(3)各レコードに固定長のデータ長はもたない
(4)NULLフィールドのデータ長はもたない

レコードのレイアウトは以下のようになる。

 可変長でNULLではない最終フィールドの長さ
 ......
 可変長でNULLではない先頭フィールドの長さ
 NULLフラグ(NULLが許可されているフィールドにつき1bit。byte単位で確保される)
 レコード情報 (4 bytes)
   <-- Origin of the record
 先頭レコードのデータ
 ......
 最終レコードのデータ

フィールド長:
 テーブル定義のフィールド長が255bytes以内のときは、1byte(0〜255)。
 フィールド長が256bytes以上のときは、以下のようになる
  データ長が127bytes以内のときは1byte。(0〜127)
  データ長が128以上のときは2byteが使用される。先頭ビットは常に1で、
  2番目のビットはextern storage flagとして使用される。データ長として
  使用できるのは14 bits(128〜16383)。

レコード情報:
 未使用 (2 bits)
 削除フラグ (1 bit)
 min_rec_flag (1 bit)
 このレコードが保持しているレコード数 (4 bits)
 レコード番号 (13 bits)
 レコードタイプ (3 bits)
 次のレコードへのポインタ (16 bits)

レコードタイプ:
 000: conventional
 001: node pointer (inside B-tree)
 010: infimum
 011: supremum
 1xx: reserved

システムカラム

各レコードの先頭には、以下のシステム用のカラムが追加される。
(1)Row ID (6 bytes)
(2)Transaction ID (6 bytes)
(3)Rollback pointer (7 bytes)

ただし、Primary keyが定義されているときは、Row IDの代わりにPrimary keyが使用される。

Primary keyなし
 Row ID
 Transaction ID
 Rollback pointer
 ユーザー定義のカラム1
 ユーザー定義のカラム2
 .....

Primary keyあり
 Primary key (ユーザー定義のカラム1)
 Transaction ID
 Rollback pointer
 ユーザー定義のカラム2
 .....