InnoDB行记录格式(compact)

来源:互联网 发布:陈意涵用的跑步软件 编辑:程序博客网 时间:2024/09/21 08:17


1. 变长字段长度列表
       记录非NULL变长字段的长度列表; 并且安装列的循序的逆序进行放置,一列的长度如果小于255,用一字节表示,如果长度长度大于255,则用两字节表示,一字节还是两字节只对一列来讲,如果一行中既有大于255,也有小于255的,则大于255用两字节,小于255则用一字节。从分析文件的十六进制来看,如果大于255,则高字节的最高位是1.  还需要分析代码是否高位都是1,如果是,那变长的最大长度是多少?
统计每一个列中数据的长度,在统计这个信息的时候,又有多种情况,主要分定长字段和变长字段,对于定长字段,它的长度直接就是数据类型的长度,比如int类型的那就是4个字节,rowid列就是6个字节等,没有其它附加长度。对于变长字段而言,除了数据内容本身的长度外,还需要计算其数据长度的存储空间,如果字段的字义长度大于255个字节,或者字段的数据类型为BLOB的,那么需要用2个字节来存储这个字段的长度;如果定义长度小于128个字节,或者小于256个字节,但类型不是BLOB类型的,那么这个字段的数据长度用一个字节来存储,除上面2种情况之外,都用2个字节来存储

代码中的注释: rem0rec.c  rec_get_converted_size_comp_prefix()
If the maximum length of a variable-length field(这个应该是表中定义的长度)
        is up to 255 bytes, the actual length is always stored
        in one byte. If the maximum length is more than 255
        bytes, the actual length is stored in one byte for
        0..127.  The length will be encoded in two bytes when
        it is 128 or more, or when the field is stored externally.


从这个插入记录(例2)来看, 长度的表达不仅和字段的定义有关, 还和插入的长度有关, 当长度的定义大于255时,  长度大于127时, 就用两个字节来表示(如下面这个表的最后一个字段), 当是127时只用一个字节来表示, 当等于128时就用两个字节来表示(80 80), 第二字节的最高位都是1; 当一个字段的定义小于255时, 它的长度都用一个字节来表示, 不管大于还是小于127.

例1
create table mytest10(t1 VARCHAR(256), t2 VARCHAR(100), t3 CHAR(50), t4 VARCHAR(300)) ENGINE=INNODB CHARSET=lat
in1 row_format=compact;

INSERT INTO mytest10 SELECT  REPEAT('a',256), REPEAT('b', 90), REPEAT('c', 40), REPEAT('d',300);
INSERT INTO mytest10 SELECT  REPEAT('e',20), REPEAT('f', 100), REPEAT('g', 40), REPEAT('h',300);
INSERT INTO mytest10 SELECT  REPEAT('i',20), REPEAT('j', 100), REPEAT('k', 40), REPEAT('l',100);
INSERT INTO mytest10 SELECT  REPEAT('q',200), REPEAT('r', 100), REPEAT('s', 40), REPEAT('t',150);
INSERT INTO mytest10 SELECT  REPEAT('u',128), REPEAT('v', 100), REPEAT('w', 40), REPEAT('x',127);


分析文件的长度列表如下  [上面十进制,下面十六进制]
INSERT INTO mytest10 SELECT  REPEAT('a',256), REPEAT('b', 90), REPEAT('c', 40), REPEAT('d',300);
300     90   256    null标志
2c 81  5a   00 81 00

INSERT INTO mytest10 SELECT  REPEAT('e',20), REPEAT('f', 100), REPEAT('g', 40), REPEAT('h',300);
300    100  20
2c 81  64   14  00

INSERT INTO mytest10 SELECT  REPEAT('i',20), REPEAT('j', 100), REPEAT('k', 40), REPEAT('l',100);
100 100 20
64   64  14 00 

INSERT INTO mytest10 SELECT  REPEAT('q',200), REPEAT('r', 100), REPEAT('s', 40), REPEAT('t',150);
150    100   200
96 80 64     c8  80 00

INSERT INTO mytest10 SELECT  REPEAT('u',128), REPEAT('v', 100), REPEAT('w', 40), REPEAT('x',127);
127 100   128
7f    64     80 80 00

例2

从这个插入记录来看, 长度的表达不仅和字段的定义有关, 还和插入的长度有关, 当长度的定义大于255时,  长度大于127时, 就用两个字节来表示(如下面这个表的最后一个字段), 当是127时只用一个字节来表示, 当等于128时就用两个字节来表示(80 80); 当一个字段的定义小于255时, 它的长度都用一个字节来表示, 不管大于还是小于127.
create table mytest20(t1 VARCHAR(200), t2 VARCHAR(127), t3 VARCHAR(128), t4 VARCHAR(300)) ENGINE=INNODB CHARSET=lat
in1 row_format=compact;

INSERT INTO mytest20 SELECT  REPEAT('e',150), REPEAT('f', 100), REPEAT('g', 128), REPEAT('h',127);

127 128  100  150
7f    80    64    96 00


INSERT INTO mytest20 SELECT  REPEAT('i',200), REPEAT('j', 100), REPEAT('k', 128), REPEAT('l',128);

128      128   100  200
80 80   80      64   c8 00


2. NULL标志位
        指示了该行数据列中是否有NULL值,这个字段的长度和表的列数有关,每一列对应一个bit位,低字节对应与高的列,即从右到左,分别对应第一列,第二列. . .(整个nulls空间中的位图是以从后面向前面的顺序来表示所有nullable列的null信息的。)。
(A single bit per nullable field to store whether the field isNULL, rounded up to a whole number of bytes. If a field is NULL its field value will be eliminated from the key or row portion of the record. If no fields are nullable, this bitmap is absent.)

create table mytest1(t1 VARCHAR(10), t2 VARCHAR(10), t3 CHAR(10), t4 VARCHAR(10), t5 VARCHAR(10) , t6 VARCHAR(10) , t7 VARCHAR(10), t8 VARCHAR(10), t9 VARCHAR(10), t10 VARCHAR(10), t11 VARCHAR(10), t12 VARCHAR(10), t13 VARCHAR(10), t14 VARCHAR(10), t15 VARCHAR(10), t16 VARCHAR(10), t17 VARCHAR(10), t18 VARCHAR(10)) ENGINE=INNODB CHARSET=latin1 row_format=compact;

INSERT INTO mytest1 VALUES(NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
NULL标志:  03 ff ff

INSERT INTO mytest1 VALUES('a', 'bb', 'cccc', 'ddd', 'eeee', 'ffffff', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
NULL标志:  03 ff c0  (000 0011 1111 1111 1100 0000)   最后的6位表示 1, 2, 3, 4, 5, 6列不是NULL

INSERT INTO mytest1 VALUES('aaaa', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
NULL标志:  03 ff fe (1110)

INSERT INTO mytest1 VALUES('a', 'bb', NULL'ddd', 'eeee', 'ffffff', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
NULL标志:   03 ff c4 (1100 0100)  



3. 记录头信息
         记录信息头的固定部分
Name
Size
Description
info_bits:
??
??
()1 bitunused or unknown
()
1 bit
unused or unknown
deleted_flag
1 bit
1 if record is deleted:   该行是否已被删除(meaning the record is delete-marked (and will be actually deleted by a purge operation in the future).)
min_rec_flag
1 bit
1 if record is predefined minimum record: 如果为1,如果该记录是预先被定义为最小记录(meaning this record is the minimum record in a 
non-leaf level of the B+Tree): 对于非叶子页的最左记录,其上有一个标志REC_INFO_MIN_REC_FLAG (0x10UL),而叶子页没有这个标志
n_owned
4 bits
number of records owned by this record:该记录拥有的记录数(The number of records “owned” by the current record in the page directory.)
heap_no13 bitsrecord's order number in heap of index page 索引堆中该记录的排序记录record_type3 bits记录类型: 000 普通记录;001 表示B+树节点指针;010 表示Infimum记录;011 表示Supremum记录,1xx 保留next_record16 bits页中下一条记录的相对位置: 即下一条记录起始地址相对于本记录的偏移。

4. 紧接着记录头信息的三个列是系统列:
RowID :                    当没有主键时, 这个字段由Innodb自动创建的, 如果有主键时, 就用主键:   6bytes
Transaction ID:        6 bytes
Roll Pointer             7 bytes 


Roll Pointer的结构
bits     55: 1 INSERT           |        54 ~48               |    47 ~ 16                                       |                         0 ~ 15                                     |
         --------------------------------------------------------------------------------------------------------- ------------------------------------------------
          |INSERT or UPDATE | rollback segment ID  |   undo log segment page number  | undo log record offset in undo log segment page |


0 0