InnoDB行记录格式(compact)



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 is NULL , 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 11 00 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 f e  (111 0 )

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 (11 00 0 1 00 )  



3. 记录头信息
         记录信息头的固定部分
Name
Size
Description
info_bits:
??
??
() 1 bit unused 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_no 13 bits record's order number in heap of index page 索引堆中该记录的排序记录
record_type 3 bits 记录类型: 000 普通记录;001 表示B+树节点指针;010 表示Infimum记录;011 表示Supremum记录,1xx 保留
next_record 16 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 |


  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值