MySql--InnoDB的表空间

MySql--InnoDB的表空间

具体细节 请去掘金购买《MySQL 是怎样运行的:从根儿上理解 MySQL》

表空间都是由页组成的

  • 1.通过页的类型知道该页的作用
  • 2.不同的页只有File Header和File Trailer是必须存在的
  • 3.每个表空间中一个页有一个页号,是4个字节,也就是32比特,所以最多有2³²个页
  • 4.如果每个页默认大小16KB则一个表空间最多支持64TB,页号从0开始。
  • 5.而是根据FIL_PAGE_PREV和FIL_PAGE_NEXT来存储上一个页和下一个页的页号。需要注意的是,这两个字段主要是为了INDEX类型的页--也就是说其他页是不使用链表来进行连接。

独立表空间结构

  • 1.因为表空间里面页太多了,所以提出区的概念
  • 2.对于16KB的页来说,连续64个页就是一个区,也就是说一个区默认是1MB空间大小。
  • 3.不论是系统表空间还是独立表空间,都可以看出若干个区组成的。
  • 4.每256个区被划分为成一组
  • 5.每个组的最开始的几个页面类型是固定的
  • 6.设置区的原因是因为:为某个索引分配空间的时候就不再按照页为单位分配了,而是按照区为单位分配,甚至在表中的数据十分非常特别多的时候,可以一次性分配多个连续的区
    这样的好处就是我们如果返回查询时候,在物理空间上页很近这就是顺序IO,如果只按照页分配,那么页有可能
    是物理上很远这就会发生随机IO。

  • 1.上述第六点说的很明白了,为啥使用区。
  • 2.如果不区分叶子节点和非叶子节点使用的区的话,就有可能会有部分叶子节点在A区,部分叶子节点在B区
  • 3.这样就会导致我们范围查询效果不太好,因此叶子节点有自己独有的区,非叶子节点也有自己独有的区。
  • 4.各个区的集合就是段,就是说一个索引会生成2个段,一个叶子节点段,一个非叶子节点段。
  • 5.这个段和组不一样,组只是区的集合不区分是否为叶子节点,而段是区分是否为叶子节点的区集合。
  • 6.段是以区为单位申请存储空间的,一个区默认占用1M存储空间,为了避免每个索引都需要申请一个2M内存,提出了一个碎片(fragment)区。
  • 7.碎片区中的页可以用于不同的目的,比如有些页用于段A,有些页用于段B,有些页甚至哪个段都不属于
  • 8.碎片区直属于表空间,并不属于任何一个段。

段分配存储空间的策略

  • 1.在刚开始向表中插入数据的时候,段是从某个碎片区以单个页面为单位来分配存储空间的
  • 2.当某个段已经占用了32个碎片区页面之后,就会以完整的区为单位来分配存储空间。

区的分类

  • 1.空闲的区:现在还没有用到这个区中的任何页面。--FREE
  • 2.有剩余空间的碎片区:表示碎片区中还有可用的页面。--FREE_FRAG
  • 3.没有剩余空间的碎片区:表示碎片区中的所有页面都被使用,没有空闲页面。--FULL_FRAG
  • 4.附属于某个段的区。每一个索引都可以分为叶子节点段和非叶子节点段,除此之外InnoDB还会另外定义一些特殊作用的段,在这些段中的数据量很大时将使用区来作为基本的分配单位--FSEG
  • 5.处于FREE、FREE_FRAG以及FULL_FRAG这三种状态的区都是独立的,而处于FSEG状态的区是附属于某个段的

XDES Entry

  • 1.每一个区都对应着一个XDES Entry结构,结构记录了对应的区的一些属性,具体如下:
  • 2.Segment ID--每一个段都有一个唯一的编号,用ID表示。前提是该区已经被分配给某个段了,不然的话该字段的值没啥意义
  • 3.List Node--这个部分可以将若干个XDES Entry结构串联成一个链表,大家看一下这个List Node的结构:Pre Node Page Number和Pre Node Offset的组合就是指向前一个XDES Entry的指针和Next Node Page Number和Next Node Offset的组合就是指向后一个XDES Entry的指针。
  • 4.State-也就是FREE、FREE_FRAG、FULL_FRAG和FSEG
  • 5.Page State Bitmap--这个部分共占用16个字节,也就是128个比特位。我们说一个区默认有64个页,这128个比特位被划分为64个部分,每个部分2个比特位,对应区中的一个页
    比如Page State Bitmap部分的第1和第2个比特位对应着区中的第1个页面,第3和第4个比特位对应着区中的第2个页面,
    这两个比特位的第一个位表示对应的页是否是空闲的,第二个比特位还没有用.

XDES Entry链表

某个段中插入数据的过程:

  • 1.当段中数据较少的时候,首先会查看表空间中是否有状态为FREE_FRAG的区
  • 2.如果找到了,那么从该区中取一些零碎的页把数据插进去;否则到表空间下申请一个状态为FREE的区,也就是空闲的区,把该区的状态变为FREE_FRAG.
    然后从该新申请的区中取一些零碎的页把数据插进去.
  • 3.之后不同的段使用零碎页的时候都会从该区中取,直到该区中没有空闲空间,然后该区的状态就变成了FULL_FRAG。
  • 4.当段中数据已经占满了32个零散的页后,就直接申请完整的区来插入数据了。

如何快速知道表空间的区处于什么状态。(表空间维护三个链表)

  • 1.把状态为FREE的区对应的XDES Entry结构通过List Node来连接成一个链表,这个链表我们就称之为FREE链表
  • 2.把状态为FREE_FRAG的区对应的XDES Entry结构通过List Node来连接成一个链表,这个链表我们就称之为FREE_FRAG链表。
  • 3.把状态为FULL_FRAG的区对应的XDES Entry结构通过List Node来连接成一个链表,这个链表我们就称之为FULL_FRAG链表。

我们怎么知道哪些区属于哪个段的呢

  • 1.为每个段中的区对应的XDES Entry结构建立了三个链表:
  • 2.FREE链表:同一个段中,所有页面都是空闲的区对应的XDES Entry结构会被加入到这个链表。注意和直属于表空间的FREE链表区别开了,此处的FREE链表是附属于某个段的。
  • 3.NOT_FULL链表:同一个段中,仍有空闲空间的区对应的XDES Entry结构会被加入到这个链表
  • 4.FULL链表:同一个段中,已经没有空闲空间的区对应的XDES Entry结构会被加入到这个链表。
  • 5.每一个索引都对应两个段,每个段都会维护上述的3个链表。

链表基节点--找到某个链表的头节点或者尾节点在表空间中的位置

  • 1.设计了一个叫List Base Node的结构--每个链表都对应这么一个List Base Node
  • 2.结构如下:List Length-表明该链表一共有多少节点
  • 3.First Node Page Number和First Node Offset表明该链表的头节点在表空间中的位置
  • 4.Last Node Page Number和Last Node Offset表明该链表的尾节点在表空间中的位置
  • 5.一般我们把某个链表对应的List Base Node结构放置在表空间中固定的位置,这样想找定位某个链表就变得so easy啦。

链表小结

  • 表空间是由若干个区组成的,每个区都对应一个XDES Entry的结构,直属于表空间的区对应的XDES Entry结构可以分成FREE、FREE_FRAG和FULL_FRAG这3个链表;
    每个段可以附属若干个区,每个段中的区对应的XDES Entry结构可以分成FREE、NOT_FULL和FULL这3个链表。
    每个链表都对应一个List Base Node的结构,这个结构里记录了链表的头、尾节点的位置以及该链表中包含的节点数。
    正是因为这些链表的存在,管理这些区才变成了一件so easy的事情。

段的结构

  • 1.段其实不对应表空间中某一个连续的物理区域,而是一个逻辑上的概念
  • 2.定义了一个INODE Entry结构来记录一下段中的属性
  • 3.Segment ID:就是指这个INODE Entry结构对应的段的编号(ID)
  • 4.NOT_FULL_N_USED:这个字段指的是在NOT_FULL链表中已经使用了多少个页面。下次从NOT_FULL链表分配空闲页面时可以直接根据这个字段的值定位到。而不用从链表中的第一个页面开始遍历着寻找空闲页面。
  • 5.3个List Base Node:分别为段的FREE链表、NOT_FULL链表、FULL链表定义了List Base Node
  • 6.Magic Number:这个值是用来标记这个INODE Entry是否已经被初始化了(初始化的意思就是把各个字段的值都填进去了)
  • 7.Fragment Array Entry:4个字节,对应着零散的页面集合。

各类型页面详细情况

FSP_HDR类型

  • 1.它存储了表空间的一些整体属性以及第一个组内256个区的对应的XDES Entry结构
  • 2.第一个组的第一个页面,当然也是表空间的第一个页面,页号为0

FSP_HDR的五个部分

  • 1.File Header:页的一些通用信息
  • 2.File Space Header:表空间的一些整体属性信息
  • 3.XDES Entry:存储本组256个区对应的属性信息
  • 4.Empty Space:用于页结构的填充,没啥实际意义
  • 5.File Trailer:校验页是否完整

File Space Header

  • 1.存储直属表空间的基节点
  • 2.FREE_FRAG链表中已经使用的页面数量,方便之后在链表中查找空闲的页面。
  • 3.FREE Limit--在该字段表示的页号之前的区都被初始化了,之后的区尚未被初始化。
  • 4.Next Unused Segment ID:通过这个为新创建的段设置ID。
  • 5.Space Flags:表空间的一些布尔值属性。
  • 6.每个段对应的INODE Entry结构会集中存放到一个类型位INODE的页中
  • 7.INODE类型的页会组成两种列表:
  • 8.SEG_INODES_FULL链表:该链表中的INODE类型的页面都已经被INODE Entry结构填充满了,没空闲空间存放额外的INODE Entry了
  • 9.SEG_INODES_FREE链表:该链表中的INODE类型的页面都已经仍有空闲空间来存放INODE Entry结构。

XDES Entry部分

  • 1.XDES Entry就是在表空间的第一个页面中保存的
  • 2.我们知道一个XDES Entry结构的大小是40字节,但是一个页面的大小有限,只能存放有限个XDES Entry结构,所以我们才把256个区划分成一组,在每组的第一个页面中存放256个XDES Entry结构

XDES类型

  • 1.所以我们把表空间的区分为了若干个组,每组开头的一个页面记录着本组内所有的区对应的XDES Entry结构
  • 2.于第一个组的第一个页面有些特殊,因为它也是整个表空间的第一个页面,所以除了记录本组中的所有区对应的XDES Entry结构以外,还记录着表空间的一些整体属性,这个页面的类型就是我们刚刚说完的FSP_HDR类型,整个表空间里只有一个这个类型的页面
  • 3.,我们把之后每个分组的第一个页面的类型定义为XDES,它的结构和FSP_HDR类型是非常相似的--除了少了File Space Header部分之外,也就是除了少了记录表空间整体属性的部分之外,其余的部分是一样一样的

IBUF_BITMAP类型

  • 1.每个分组的第二个页面的类型都是IBUF_BITMAP
  • 2.这种类型的页里边记录了一些有关Change Buffer

INODE类型

  • 1.第一个分组的第三个页面的类型是INODE
  • 2.每个索引定义了两个段,而且为某些特殊功能定义了些特殊的段。为了方便管理,他们又为每个段设计了一个INODE Entry结构
  • 3.一个INODE类型的页面是由这几部分构成的:
  • 4.File Header,List Node for INODE Page List,INODE Entry,Empty Space,File Trailer
  • 5.INODE Entry:对应的段内零散页面的地址以及附属于该段的FREE、NOT_FULL和FULL链表的基节点
  • 6.List Node for INODE Page List:SEG_INODES_FULL链表和SEG_INODES_FREE链表

Segment Header 结构的运用

  • 1.一个索引会产生两个段,分别是叶子节点段和非叶子节点段,而每个段都会对应一个INODE Entry结构,那我们怎么知道某个段对应哪个INODE Entry结构呢
  • 2.也就是INDEX类型的页时有一个Page Header部分的Segment Header 就是记录这些信息的。
  • 3.具体的内容是:Space ID of the INODE Entry,Page Number of the INODE Entry,Byte Offset of the INODE Entry

系统表空间

  • 1.表空间 ID(Space ID)是0
  • 2.系统表空间和独立表空间的前三个页面(页号分别为0、1、2,类型分别是FSP_HDR、IBUF_BITMAP、INODE)的类型是一致的
  • 3.只是页号为3~7的页面是系统表空间特有的:SYS(存储Insert Buffer的头部信息),INDEX(存储Insert Buffer的根页面),TRX_SYS(事务系统的相关信息),SYS(第一个回滚段的页面),SYS(数据字典头部信息)
  • 4.系统表空间的extent 1和extent 2这两个区,也就是页号从64~191这128个页面被称为Doublewrite buffer,也就是双写缓冲区

InnoDB数据字典

元数据是哪些

  • 1.某个表属于哪个表空间,表里边有多少列
  • 2.表对应的每一个列的类型是什么
  • 3.该表有多少索引,每个索引对应哪几个字段,该索引对应的根页面在哪个表空间的哪个页面
  • 4.该表有哪些外键,外键对应哪个表的哪些列
  • 5.某个表空间对应文件系统上文件路径是什么
  • 6.等等

innodb定义了许多内部系统表来记录元数据(也就是数据字典)

  • 1.SYS_TABLES 整个InnoDB存储引擎中所有的表的信息
  • 2.SYS_COLUMNS 整个InnoDB存储引擎中所有的列的信息
  • 3.SYS_INDEXES 整个InnoDB存储引擎中所有的索引的信息
  • 4.SYS_FIELDS 整个InnoDB存储引擎中所有的索引对应的列的信息
  • 5.SYS_FOREIGN 整个InnoDB存储引擎中所有的外键的信息
  • 6.SYS_FOREIGN_COLS 整个InnoDB存储引擎中所有的外键对应列的信息
  • 7.SYS_TABLESPACES 整个InnoDB存储引擎中所有的表空间信息
  • 8.SYS_DATAFILES 整个InnoDB存储引擎中所有的表空间对应文件系统的文件路径信息
  • 9.SYS_VIRTUAL 整个InnoDB存储引擎中所有的虚拟生成列的信息
  • 10.SYS_TABLES、SYS_COLUMNS、SYS_INDEXES、SYS_FIELDS这四个表尤其重要,称之为基本系统表(basic system tables)
  • 11.只要有了上述4个基本系统表,也就意味着可以获取其他系统表以及用户定义的表的所有元数据

Data Dictionary Header页面(数据字典的头部信息)

  • 1.这4个表是表中之表,那这4个表的元数据去哪里获取呢
  • 2.拿出一个固定的页面来记录这4个表的聚簇索引和二级索引对应的B+树位置,这个页面就是页号为7的页面,类型为SYS,记录了Data Dictionary Header
  • 3.Max Row ID:每个表如果没有主键或者唯一索引,那么innodb就生成主键,该属性就是记录整个innodb的Max rou id
  • 4.Max Table ID:InnoDB存储引擎中的所有的表都对应一个唯一的ID,每次新建一个表时,就会把本字段的值作为该表的ID,然后自增本字段的值。
  • 5.Max Index ID:InnoDB存储引擎中的所有的索引都对应一个唯一的ID,每次新建一个索引时,就会把本字段的值作为该索引的ID,然后自增本字段的值。
  • 6.Max Space ID:InnoDB存储引擎中的所有的表空间都对应一个唯一的ID,每次新建一个表空间时,就会把本字段的值作为该表空间的ID,然后自增本字段的值。
  • 7.Root of SYS_TABLES clust index:本字段代表SYS_TABLES表聚簇索引的根页面的页号
  • 8.Root of SYS_TABLE_IDS sec index:本字段代表SYS_TABLES表为ID列建立的二级索引的根页面的页号。
  • 9.Root of SYS_COLUMNS clust index:本字段代表SYS_COLUMNS表聚簇索引的根页面的页号。
  • 10.Root of SYS_INDEXES clust index本字段代表SYS_INDEXES表聚簇索引的根页面的页号。
  • 11.Root of SYS_FIELDS clust index:本字段代表SYS_FIELDS表聚簇索引的根页面的页号。

information_schema系统数据库

  • 1.用户是不能直接访问InnoDB的这些内部系统表的
  • 2.这个数据库里面的表示对上述系统表的一个视图。

总结图

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

推荐阅读更多精彩内容

  • 1 内存寻址 1.1 物理地址、虚拟地址以及线性地址 物理地址: 物理内存的内存单元地址 虚拟地址: 程序员看到的...
    疯狂小王子阅读 2,715评论 3 21
  • 概述 我们都知道一个进程是与其他进程共享CPU和内存资源的。正因如此,操作系统需要有一套完善的内存管理机制才能防止...
    SylvanasSun阅读 3,749评论 0 25
  • 进程 创建 创建进程用fork()函数。fork()为子进程创建新的地址空间并且拷贝页表。子进程的虚拟地址空间...
    梅花怒阅读 1,791评论 0 7
  • 一、温故而知新 1. 内存不够怎么办 内存简单分配策略的问题地址空间不隔离内存使用效率低程序运行的地址不确定 关于...
    SeanCST阅读 7,667评论 0 27
  • 蹭热度的标题? 我说的是真的! 距离京津城际开车还有半小时,收到临时线下见面的消息。 香港第一金融自媒体大咖,赫赫...
    2512e4db14f4阅读 270评论 3 1