InnoDB引擎逻辑存储结构

(本片博文是《MySQL技术内幕 InnoDB存储引擎第二版》的读书笔记)

索引组织表

InnoDB存储引擎中,表都是按照主键顺序组织存放的,这种存储方式的表称为索引组织表(index organized table)。InnoDB存储引擎表中,每张表都有个主键,若在创建表时没有显式定义主键则InnoDB存储引擎会按如下方式选择或者创建主键:

  • 首先判断表中是否有非空的唯一索引(Unique NOT NULL),如果有,则该列即为主键。(当表中有多个非空唯一索引时,InnoDB存储引擎将选择建表时第一个定义的非空唯一索引为主键,注意是根据定义索引的顺序而不是建表时列的顺序)。
  • 如果不符上述条件,则会自动创建一个6字节大小的指针。

InnoDB逻辑存储结构

这是《MySQL技术内幕 InnoDB存储引擎》一书中对InnoDB逻辑存储结构的描述。


1.PNG

表空间

表空间是Innodb存储引擎逻辑的最高层,所有的数据都存放在表空间中,默认情况下,Innodb存储引擎有一个共享表空间ibdata1,即所有数据都存放在这个表空间中内。如果启用了innodb_file_per_table参数,则每张表内的数据可以单独放到一个表空间内,但请注意,只有数据、索引、和插入缓冲Bitmap放入单独表内,其他数据,比如回滚(undo)信息、插入缓冲检索页、系统事物信息,二次写缓冲等还是放在原来的共享表内的。

从上图中可以看出表空间由段组成,常见的段有数据段、索引段、回滚段等。因为InnoDB存储引擎表是索引组织的,因此数据即索引,索引即数据。数据段即为B+树的叶子结点,索引段即为B+树的非索引结点。在InnoDB存储引擎中对段的管理都是由引擎自身所完成,DBA不能也没必要对其进行控制。

区是由连续页组成的空间,在任何情况下每个区的大小都为1MB。为了保证区中页的连续性,InnoDB存储引擎一次从磁盘申请4~5个区。默认情况下,InnoDB存储引擎页的大小为16KB,一个区中一共64个连续的区。

页(块)

页是InnoDB磁盘管理的最小单位。在InnoDB存储引擎中,默认每个页的大小为16KB。从InnoDB1.2.x版本开始,可以通过参数innodb_page_size将页的大小设置为4K,8K,16K。若设置完成,则所有表中页的大小都固定,不可以对其再次修改。除非通过mysqldump导入和导出操作来产生新的库。
InnoDB存储引擎中,常见的页类型有:数据页,undo页,系统页,事务数据页,插入缓冲位图页,插入缓冲空闲列表页等。

InnoDB数据页结构

InnoDB数据页结构如下图:

1.PNG

其中File Header、Page Header、File Trailer的大小是固定的,分别为38,56,8字节,这些空间用来标记该页的一些信息,如Checksum,数据页所在B+树索引的层数等。User Records、Free Space、Page Directory这些部分为实际的行记录存储空间,因此大小是动态的。

1.File Header用来记录页的一些头信息,由表中8个部分组成,共占38字节。各部分代表信息如下表所示:

1.PNG

2.PNG

2.Page Header用来记录数据页的状态信息,14个部分组成,共占56字节。各部分代表信息如下表所示:

1.PNG

2.PNG

3.Infimum和Supermum Record是InnoDB中两个虚拟的行记录,用来限定记录的边界。Infimum记录是比该页中任何主键值都要小的值,Supermum是比任何可能大的值还要大的值。这两个记录在页创建时被建立,并且在任何情况下都不会被删除。下图显示了Infimum记录和Supermum记录:
3.PNG

4.User Record和Free Space

User Record就是实际存储行记录的内容。InnoDB存储引擎表总是B+树索引组织的。Free Space指空闲空间,是链表数据结构,在一条记录被删除后,该空间会被加入到空闲链表中。
5.Page Directory

Page Directory中存放了记录的相对位置(是页相对位置而不是偏移量),有时这些记录指针称为Slots(槽)或者目录槽(Directory Slots)。与其他数据库系统不同的是,在InnoDB中并不是每个记录拥有一个槽,InnoDB存储引擎的槽是一个稀疏目录(sparse directory),即一个槽中可能包含多个纪录。伪记录的Infimum的n_owned值总是为1,记录Supermum的n_owned的取值范围为[1,8],其他用户记录n_owned的取值范围为[4,8]。当记录被插入或删除时需要对槽进行分裂或平衡的维护操作。

在Slots中记录按照索引键值顺序存放,这样可以利用二叉查找迅速找到记录的指针。假设有('i','d','c','b','e','g','l','h','f','j','k','a'),同时假设一个槽中包含4条记录,则Slots中的记录可能是('a','e','i')。

由于在InnoDB存储引擎中Page Directory是稀疏目录,二叉查找的结果只是一个粗略结果,因此InnoDB存储引擎必须通过recorder header中的next_record来继续查找相关记录。同时,Page Directory很好地解释了recorder header中的n_owned值的含义,因为这些记录并不包括在Page Directory中。

B+树索引本身并不能找到具体的一条记录,能找到只是改记录所在的页。数据库把页载入到内存,然后通过Page Directory再进行二叉查找。只不过二叉查找的时间复杂度很低,同时在内存中的查找很快,因此通常忽略这部分查找所用的时间。

6.File Trailer
该部分是为了检测页是否已经完整地写入磁盘的(可能在写入过程中磁盘损坏、机器关机等)。该部分占用8字节,前4字节代表该页的checksum值,后4字节和File Header中的FIL_PAGE_LSN相同。将这两个值与File Header中的FIL_PAGE_SPACE_OR_CHKSUM和FIL_PAGE_LSN值进行比较,看是否一致(checksum的比较需要通过InnoDB的checksum函数来比较,不是简单的等值比较),以此来保证页的完整新。

InnoDB存储引擎是面向列的,也就是说数据按行存放。每个页存放的行记录也是有硬性定义的,最多允许存放16KB/2-200=7992行记录。
InnoDB存储引擎提供了Compact和Redundant两种格式来存放行记录数据,Redundant格式是为兼容之前版本而保留的。5.1版本中,默认设置为Compact行格式。可以通过命令SHOW TABLE STATUS LIKE 'table_name'来查看当前表使用的行格式,其中row_format属性表示行记录类型。

Compact行记录格式

3.PNG

上图就是Compact行记录的存储方式。由图可知,首部是一个非NULL变长字段长度列表,并且是按照列的顺序逆序放置的,长度为:

  • 若列的长度小于255字节,用1字节表示;
  • 若大于255字节,用2字节表示。

变长字段的长度最大不可以超过2字节,因为在MySQL中VARCHAR类型的最大长度限制为65535。变长字段之后的第二个部分是NULL标志位,指示了该行数据中是否有NULL值,有则用1表示,占1字节。接下来是记录头信息,固定占用5字节。每位的含义见下表

4.PNG

最后的部分就是实际存储每个列的数据。NULL不占该部分任何空间,即NULL除了占有NULL标志位,实际存储不占有任何空间。另外有一点需要注意的是,每行数据除了用户定义的列外,还有两个隐藏列,事务ID和回滚指针列,分别为6字节和7字节的大小。若InnoDB表没有定义主键,每行还会增加一个6字节的rowid列。

Redundant行记录格式

Redundant是MySQL5.0版本之前InnoDB的行记录存储方式,MySQL5.0支持Redundant是为了兼容之前版本的页格式。Redundant行记录采用如图所示的方式存储。

1.PNG

首部是字段长度偏移列表,按照列的顺序逆序放置。若列的长度小于255字节,用1字节表示;若大于255字节,用2字节表示。第二部分为记录头信息,占用6字节,每位含义如下表
2.PNG

从表中可以看出,n_fields值代表一行中列的数量,占用10位,很好的解释了为什么MySQL数据库一行支持最多的列为1023。另一个需要知道的是1byte_offs_flags,该值定义了偏移列表占用1字节还是2字节。最后的部分就是实际存储的每个列的数据了。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 221,695评论 6 515
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 94,569评论 3 399
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 168,130评论 0 360
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 59,648评论 1 297
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 68,655评论 6 397
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 52,268评论 1 309
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,835评论 3 421
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,740评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 46,286评论 1 318
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,375评论 3 340
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,505评论 1 352
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 36,185评论 5 350
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,873评论 3 333
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,357评论 0 24
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,466评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,921评论 3 376
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,515评论 2 359

推荐阅读更多精彩内容