一、InnoDB之一条记录的结构

一、页

InnoDB将数据存储在磁盘上,真正处理数据的行为发生在内存里。所以操作数据时,需要将数据在磁盘与内存来回交换,Innodb采用页作为交换的基本单位,一页一般16KB大小。也就是说Innodb一次最少从磁盘里读取16KB的数据到内存中,同样最少写入16KB的数据到磁盘。

二、InnoDB的行格式

平时,我们哪知道Innodb操作的是一页一页的数据,看到的都是一行一行的。这种一行一行的记录简称‘行格式’吧。它们也是有固定的格式,Innodb的设计者设计了4种行格式,分别是Compact、Dynamic、Compress和Redundant。

  1、Compact行格式

Compact行格式

一行记录分为额外信息与真实数据两部分,在进一步。

1.1、变长字段的长度列表

    当列的格式是变长格式时,Innodb将真实内容与数据的真实长度分开存放,例如varchar(M),text等。当格式为定长格式(例如char(M))时,则不会将该列的长度信息保存在此处。但是这种情况仅适用于定长字符集,也就是一个字节就代表一个字符;如果字符集选用变长字符集时,例如utf8使用1~3个字节表示一个字符时,char(M)格式的列也需要将真实长度列表记录在额外信息里。对于char(M)采用变长字符集时,即使此列不存任何值,也至少占用M个字节,这是怕将来更新内容时如果新值长度小于M就能就地更新,不用重新分配空间。

    另外列的真实长度在此处保存的顺序是逆序存放的。并且如果某列的真实长度超过一个字节时,就会用两个字节表示。如果所有的列都采用定长字符集、定长格式时,变长字段的长度列表就没有必要存在了。

    保存一列的真实长度时,会根据字符数量M、字符集字节数W、真实记录长度L选择一个字节还是两个字节。W*M<=255时用一个字节;W*M>255时,如果L<=127,用一个字节,L>127时用两个字节。

1.2、NULL值列表

    当列的定义可为NULL时,就会在对应的bit上标记为1,同样是逆序存放。如果所有列定义都不能为null时,那么NULL值列表同样没有必要存在。NULL值列表规定必须使用整个字节表示,当你有一列格式可为null时,NULL值列表会使用一个字节保存,其他位补0。当你有9列可为null时,将使用2个字节保存。

1.3、记录的头信息

Compact记录的头信息
字段名大小 bit描述作用
delete_mask1标记是否删除只是标记为删除,这条记录的空间并没有直接被回收,还可以被重新利用。并且这种状态很适合进行事务处理
min_rec_mask1用来标记B+树非子节点的最小记录用来建立B+树索引的
n_owned4表示当前拥有的记录数每页可能存储很多条记录,于是页又把记录进行分组。每组生成一个目录slot,将目录slot存在页的page_directory字段里。最小记录为单独的一组,n_owned就是1咯。每组的最后一条记录的n_owned记录的就是本组的记录数量
heap_no13表示当前记录在记录堆中位置信息记录在页中的相对位置。最小记录与最大纪录分别为0,1。我们插入的第一条记录就从2开始
record_type3标记记录类型0:普通记录(就是行数据)  1:表示B+树非叶子节点记录  2:最小记录  3:最大记录
next_record16下一条记录的相对位置。行记录是以主键组成的递增的单向链表你也懂了吧

 

1.4、记录的真实数据

    真实数据除了我们定义的列,MySQL还可能自动生成三个隐藏列:

隐藏列
列明是否必须描述
DB_ROW_ID行记录的唯一标识。如果我们自定义了主键或唯一索引,此列就不需要存在了
DB_TRX_ID事务ID。

DB_ROLL_PTR

回滚

 

每一个行记录都有这三列(如果明确指定主键或唯一索引,DB_ROW_ID就不存在)。

剩下两个隐藏列是InnoDB实现行锁的关键属性

  2、Redundant行格式

这种格式是MySQL5.0之前用的,很老套了。大致如下

Redundant

与Compact格式相比,没有了NULL值列表。

2.1、字段长度的偏移列表

    redundant行格式会把该条记录中所有列(包括隐藏列)的长度信息都按照逆序存储到字段长度的偏移列表。并且保存的是两个相邻列真是内容长度的差值。

   并且记录的头信息也略有变化:

Redundant记录的头信息
字段名大小 bit描述
delete_mask1标记是否删除,删除的记录并不会立马被回收哦
min_rec_mask1用来标记B+树非子节点的最小记录
n_owned4表示当前拥有的记录数
heap_no13表示当前记录在记录堆中位置信息
n_field10表示记录中列的数量
1byte_offs_flag1标记字段长度偏移列表中每个列对应的偏移量是使用1字节还是2字节表示的
next_record16下一条记录的相对位置。行记录是以主键组成的递增的单向链表

 

  redundant行格式不会在乎什么可变长度字段,一开始分配M*W个字节空间。

3、Dynamic与Compress行格式

  这两种行格式与Compact模式相同。只是在处理行溢出现象时,处理方式不同。

 3.1、行溢出

  一页的大小是16KB,当一条的记录大于16KB时就会出现行溢出现象。例如varchar(M)最多占用65535个字节,相当于64KB。

Compact与Redundant会保存真实的记录内容,但对于行溢出,只会保存真实记录的前768字节,再使用20字节保存溢出页地址,溢出页里存放数据。Dynamic与Compress行格式则只保存堆(页)地址,将真实内容全部保存在堆(其实就是页)中,其中Compress还会对真实内容进行压缩。

3.2、行溢出临界点

MySQL规定一页中最少存两条记录。

如果一行只有一列,一页16384个字节,最少两条数据。每一页除了数据列,还有132个字节的关于页的其他信息,每个记录的额外信息27字节。132+2*(27+n)<16384,得出这条列的总大小要小于8099个字节。如果这列超过此值,就可能成为溢出列。真实情况是我们会有很多列,计算方式就得另算了。

所以推荐不关注临界点,但是单个列数据过长时,就要考虑有溢出的危险。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值