当前位置: 首页 > news >正文

个人网站用什么域名好邵武网站建设wzjseo

个人网站用什么域名好,邵武网站建设wzjseo,广州微网站建设效果,最近最新手机中文大全8InnoDB 是怎么存储数据的 本文是《MySQL 是怎样运行的 —— 从根儿上理解 MySQL》读书总结#xff0c;强烈推荐这本书#xff1b; CSDN 不能显示 SVG#xff0c;可能有图片加载不出来#xff0c;可以到 我的博客 上看。 数据目录 众所周之#xff0c;MySQL 的数据是存储在…InnoDB 是怎么存储数据的 本文是《MySQL 是怎样运行的 —— 从根儿上理解 MySQL》读书总结强烈推荐这本书 CSDN 不能显示 SVG可能有图片加载不出来可以到 我的博客 上看。 数据目录 众所周之MySQL 的数据是存储在硬盘中的而操作系统管理硬盘中的数据的方式就是文件系统所以通俗的来说MySQL 中的数据是存在一个个文件中的这些文件 的目录就叫 数据目录。 通过 SHOW VARIABLES LIKE datadir 可以查看这个目录 进入这个目录你会发现每个数据库对应该目录下的一个子目录比如 MySQL 中有一个 hotsong 的库Data 目录下就会有一个 hotsong 的文件夹这个文件夹里面存储的是一些 ibd 类型的文件数据库里每张表对应一个 ibd 文件 PS C:\ProgramData\MySQL\MySQL Server 8.0\Data\hotsong ls 目录: C:\ProgramData\MySQL\MySQL Server 8.0\Data\hotsongMode LastWriteTime Length Name ---- ------------- ------ ---- -a---- 2019/9/7 20:44 114688 hotsong.ibd -a---- 2019/9/7 22:37 12582912 singer.ibd -a---- 2019/9/7 21:17 114688 singer_type.ibd -a---- 2020/10/6 9:21 130023424 songs.ibd这里是 MySQL 8.0 的样子但如果你使用的是更早的版本你还会看到一种 .frm 的文件这种文件用来描述表结构8.0 之后, 表结构信息以 SDI 的形式放在了 .ibd 文件中你可以使用官方提供 的工具 idb2sdi 从 ibd 文件中提取表结构信息结果会以 json 形式输出 在 8.0 之前ibd 文件里保存的仅仅是该表的数据但是再往前MySQL 5.6.6 之前MySQL 服务器中所有表的数据都会被放在一个地方叫系统表空间 对应数据目录下的 ibdata1 文件这是一个自扩展文件但是你也可以在服务器启动时使用相关参数指定服务器使用自定义的文件。 在 5.6.6 之后InnoDB 引如 独立表空间 空间的概念每张表使用单独的文件存储数据和表结构也就是上面的 ibd 和 frm 文件服务器启动时可以通过 innodb_file_per_table 设置只使用系统表空间值为 0或者是使用独立表空间值为1. 服务启动后通过 ALERT 语句存储在两种表空间中的数据可以相互移动。 需要注意的是不是说使用了独立表空间系统表空间就没用了因为系统表空间除了可以存储表数据外还存储了许多 MySQL 服务运行所必要的公共信息。 数据目录总结 MySQL 的数据是存储在磁盘的或者可以说是存储在文件中的这些文件的目录叫做数据目录每个数据库对应数据目录下的一个子目录每个表中数据存放的地方叫表空间在 5.6.6 之前所有数据都被存放在一个地方叫系统表空间数据库子目录下只有 frm 文件用来描述表结构在 5.6.6 之后InnoDB 默认将每个表的数据放在一个单独的 ibd 文件中称为独立表空间在 8.0 之后InnoDB 将描述表结构的 frm 信息以 sdi 的形式也放在了 ibd 文件中所以 8.0 之后数据库子目录下就只有 ibd 了。 5.6.6 之后系统表空间默认只存储一些必要的公共信息对应数据目录下的 ibdata1 文件但他仍然很重要。 InnoDB 的数据存放在数据目录下的某个文件中这是把 InnoDB 看作一个黑盒从操作系统的角度得到的一个宏大的结论但每条记录是以怎样的形式组织在这个文件中的就需要深入了解表空间和记录的具体结构了。 聚簇索引和页 众所周之InnoDB 中每张表都一定会有一个聚簇索引如果该表设置了主键那就会以主键建立聚簇索引如果没有设置主键InnoDB 会选取一个唯一非 NULL 的列建立聚簇索引如果找不到适合建立聚簇索引的列InnoDB 会给表插入一个隐藏列 row_id, 并以此建立聚簇索引。 为什么 InnoDB 如此执着非要建一个聚簇索引呢原因是聚簇索引的叶子节点会存储表中的完整数据换句话说InnoDB 中的数据是存储在聚簇索引叶子节点中的。 InnoDB 的聚簇索引是一颗 B 树B 树的每个节点占一页“页” 是 InnoDB 中内存分配的基本单位大小为 16KBInnoDB 中有许多不同种类的页如移除页索引页等B 的树节点类型就是索引页它的结构如下图所示 从上往下依次是 文件头File Header:占 38 字节用来描述数据页的一些状态信息。页头Page Header: 占 56 字节记录了存储在页中的记录的一些状态。Infimum Supermum: 占 26 字节该页中两条预添加的记录Infimum 表示该页中的最小记录Supermum表示一个最大记录。User Records: 用户记录。Free Space: 空闲空间。页目录Page Directory: 用来加快页内记录查找速度。文件尾File Tialer: 用于校验数据。 File Header 文件头File Header:占 38 字节用来描述数据页的一些状态信息它的结构如下 从左到右依次表示 该页的校验和页号上一个页的页号下一个页的页号页面被最后修改时对应的日志序列号LSN页面类型仅在系统表空间的第一个页上使用页属于哪个表空间 这里面比较重要的是 FIL_PAGE_PREV 和 FIL_PAGE_NEXT ,这两个字段可以看作指向上一个页和下一个页的指针我们知道 B 树的叶子节点是通过双指针串联起来的但实际上InnoDB 的索引里它的非叶子节点也可以看作是串连起来的。 Page Header 页头Page Header: 占 56 个字节他记录了存储在页中的记录的一些状态结构如下 从上到下依次为 页目录中槽的数量后面会说还未使用的最小地址空间,也就是该地址之后就是 Free Space 了。第一位表示本记录是否为紧凑型记录后 15 为表示本页堆中的记录数。已删除记录链表的头节点的偏移。已删除的记录占用的字节数。最后插入的记录的位置。记录插入方向。一个方向连续插入的记录数。用户记录数PAGE_N_HEAP 中的记录数包含已经删除了的记录和Infimum Supermum 但这里不包含当前页的最大事务 ID。该页在 B 树中所处的层级。B 树叶子节点的头部信息只在 B 树的更页面定义B 树非叶子节点头部信息只在 B 树的更页面定义 关于第一个 PAGE_N_DIR_SLOTS , 他与页目录有关在后面会说到关于 3 4 5 9 他们都涉及到了记录的删除当我们执行 DELETE 语句时InnoDB 并不会真的把这条记录从磁盘删除因为这还涉及到紧凑数据每次都真正删除花销太大所以 InnoDB 会修改这条记录上的一个标记位并将这些已经删除的记录链在一起事实上正常记录也是链在一起的在说记录格式时会讲到4 PAGE_FREE 所记录的就是这个链表的头节点在 User Records 中的偏移。 关于 78记录插入方向描述的是新插入记录的主键值与最后一次插入记录主键值的大小关系。 User Records 到这儿就需要说一下 InnoDB 的记录行格式了。 InnoDB 行格式 行格式也就是每条记录在 InnoDB 中的真实样子InnoDB 有四种行格式分别是COMPACT REDUNDANT DYNAMIC COMPRESSED通过 ROW_FORMAT 可以修改表的行格式如 ALTER TABLE table_name ROW_FORMATCOMPACT这里以 COMPACT 格式为例它的结构如下 变长字段长度列表 顾名思义这个结构用来存储这一行里变长字段的长度唯一需要注意的是这个列表是按表结构逆序排序的假如一个表结构如下 CREATE TABLE hotsong (id int(11) NOT NULL AUTO_INCREMENT,name varchar(50) NOT NULL,song_id int(11) NOT NULL,download_link varchar(100) DEFAULT NULL,singer varchar(20) DEFAULT NULL,PRIMARY KEY (id) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4 COLLATEutf8mb4_0900_ai_ci;其中 name, download_link, singer 的类型是 varchar, 属于变长字段如果向该表中插入一条记录其中 name, download_link, singer 的长度分别为 1 2 3 则在变长字段长度列表中会存储 3 2 1。 对于列表中该使用多少字节存储一个字段的长度这取决于表采用的字符集和该类型能存储的最大字节数如上表字符集是 utf8mb4, 该字符集最多使用四个字节表示一个字符而定义中 name 最多存储 50 个字符所以这些字段能存储最多 4 * 50 200 字节的数据所以用一个字节就可以表示其长度了而 download_link 最多存储 100 个字符则需要两个字节来表示其长度了。这里最多也只会使用两个字节如果某个字段长度特别长就需要使用溢出字段了也就是在这一页中只会存部分数据。 变长字段列表只会存不为 NULL 的列的长度NULL 列会表现在下面的 NULL 值列表中。 NULL 值列表 很好理解NULL 值列表类似于一个 Bitap 表明了这一行中哪写列是 NULL这些为 NULL 的列是不会占额外的空间的存记录时 InnoDB 会去查看表格式看允许为 NULL 的列有多少个如上面的 hotsong 表只有两个字段允许为 NULL那 NULL 值列表就会占用一个字节必须占用整数字节高位填0最低两位用来表示 singer 和 download_link 这里和长度列表一样也是逆序排列的值为 0 时代表该字段不为 NULL。 记录头信息 记录头信息里我们暂且关注这几个字段 delete_flag: 标识这条记录是否被删除在 Page Header 那已经说过了这就是那个标志位为 1 表示被删除。n_owner: 与页目录有关页中的记录会被分成若干组这个字段表示这一组中的记录数。heap_no: 这条记录在页堆中的偏移。record_type: 记录类型 0 普通记录1B 树非叶子节点目录项记录2Infimum 记录3Supermum 记录 next_record: 下一个记录主键大小上的下一条的相对位置通过这个字段页面中的每条记录都像是使用链表连起来了。 回到索引页的 User Records 上通过上面行格式的介绍我们知道每一条记录的长度是不一样的并且他们通过 next_record 链在了一起所以记录在 User Records 中是像下面这样存储的 记录一条一条紧密排列这个结构被称之为 Heap(堆) 记录在这个堆中的相对位置就是上面记录头信息里的 heap_no, next_record 指的也是下一条记录的偏移而不是真的一个链表指针。 除此之外InnoDB 的设计者在每一个堆中加入了两条特殊记录Infimum 和 Supermum他们的 heap_no 分别为 0 和 1这两条记录很简单只有记录头信息和代表这两个单词的记录体这两个特殊记录代表了这一页中最大和最小的记录也就是说通过 Infimum 的 next_record 找到的是堆中的第一条用户记录堆中的最后一条用户记录的 next_record 指向了 Supermum, 如果把紧密排列的堆变成链表的样子他应该是这样的 关于 next_record 他还有一个非常重要的特性就是它允许为负表示当前记录的下一条记录在它前面这里的下一条是主键大小排列上的下一条比如页中有一个主键值为 5 的记录 A长度为 lenAlen_AlenA​我们又插入了一条主键值为 6 的记录 B长度为 lenBlen_BlenB​那么 A 的 next_record 就是 lenAlen_AlenA​ 表示沿着记录 A 向后寻找 lenAlen_AlenA​ 个字节就是记录 B但这时如果我们又插入了一条主键值为 4 的记录 C那 C 的 next_record 就是 −(lenAlenB)-(len_A len_B)−(lenA​lenB​) 也就是向前找能找到 C 的下一条记录 A。 这样的好处是通过 next_record 页中的所有记录会组成一个按主键排序的有序链表但在物理上记录还是按插入顺序紧密排列的配合下面的页目录能提高页内记录的检索速度。 Page Directory 我们知道索引的存在是为了快速定位到记录所在的页但定位到页后呢一页里可能包含许多记录遍历页中的所有记录同样是不可接受的所以 InnoDB 设计了页目录相当于页索引它的工作原理如下 将所有未删除的记录包括Infimum 和 Supermum划分为多个组。将每组中的最后一条记录的偏移提取出来放在 Page Directory 中。当查找页中的某条记录时先通过二分法查找到该记录在哪一组中然后找到这一组中最小的那条记录沿着 next_record 往下遍历这一组的记录。 这里 Page Directory 中的每一个偏移量被叫做一个 槽 一个槽占 2 字节记录分组的原则是 Infimum 独占一组Supermum 那一组只能有 1~8条记录其他组只能有 4 ~ 8 条记录 这样一来页中最多遍历 8 次就可以找到确认找不到某条记录了能这样做的前提还是通过 next_record 记录组成了一个有序链表。 还有一个有趣的问题槽中记录的是一组中最大的记录的偏移但定位到组后需要的是最小的记录该怎么办呢上一个槽的下一条记录不就是吗。 总结 第一节 数据目录 我们站在操作系统的角度说 InnoDB 是把数据存储在数据目录下的文件中的这一节我们从聚簇索引的一个节点页出发说明了一条记录是怎样被存放的关键点如下 所有数据被存放在表聚簇索引的叶子节点上。索引的一个节点就是一页大小为 16KB页是 InnoDB 内存分配的基本单位。InnoDB 中页有很多种索引的节点对应的页类型叫索引页。索引页由文件头页头用户记录页目录文件尾等部分组成。通过文件头页和页可以以双链表的形式连接起来。页头记录了页中的一些统计信息。用户记录段是存储用户记录的地方每条记录被紧密地存储在这称为堆。每条用户记录都有一个重要的 next_record 字段他能保证紧密排列地用户记录能按主键大小组织成一个有序链表。有两条特殊的记录 Infimum 和 Supermum被安排在堆中他们处于堆中最前的位置但分别表示最大最小的记录。页目录是为了提高页内记录检索的速度而存在的堆中的记录最多会 8 个为一组每一组中最大的记录偏移量会被存放在页目录中称为槽查找记录时会先通过二分法定位到组然后在组内遍历。文件尾用来校验数据。 最后放上索引页的整体图 接下来我们要把页和数据目录结合起来了解页是怎么在表空间中组织的。 InnoDB 表空间 在 MySQL 5.6.6 之后 InnoDB 有了独立表空间的概念每张表对应一个独立表空间一个 ibd 文件而系统表空间ibdata1则主要用来存储一些公有的信息这一节我们以页为单位看一看 InnoDB 是怎么在表空间中管理每个页的。 页回顾 上面多次说过页是 InnoDB 分配内存的基本单位一页大小 16KB页有许多不同的类型如 Index 页上面已经说过。Inode 页用来存储段信息。XDES 页存储区信息。FPS_HDR 页存储表空间头部信息。IBUF_BITMAP 页存储 Change Buffer 相关的内容。 除了这几个其实还有许多种类型的页但其余的和本文关系不大我们只关心这几种页就好了。 上面说 Index 页时讲了它的格式事实上File Header 和 File Trailer 是所有页面类型所共有的在后面介绍其他页面类型的结构时就不赘述了。 区 , 组和段 前面说过页是 InnoDB 分配存储空间最小的单位但问题在于页太小了只有 16KB在表中数据非常多时如果继续以页为单位分配就可能造成页与页间的物理距离过大虽然页和页之间是通过指针连接的但在使用传统机械硬盘时物理距离大就意味着根据一个页的 Next 指针找到下一个页磁头需要移动更多的距离随机 IO造成页和页虽然在逻辑上连续但在物理上分散这样不利于高效地数据读写。为了尽量避免这种情况InnoDB 会尽量让逻辑上相连的页在物理内存上也连续顺序IO具体做法就是当表中的数据量很大时就以更大的 区extent为单位为表分配存储空间InnoDB 规定连续的 64 个页是一个区也就是一个区占 1M 的空间。同时为了方便管理这些区将连续的 256 个区被划分为一组每一组的开始几个页面类型是固定的 对于表空间中第一个组的前三个页面类型是固定的他们依次是 FPS_HDR 页记录表空间的整体属性和这一组中 256 个区的整体属性。IBUF_BITMAP 页存储 Change Buffer 相关的内容。INODE 页存储与段相关的内容。 对于其他组它的前两个页面类型是固定的依次是 XDES 页记录这一组中说有区的属性IBUF_BITMAP 页存储 Change Buffer 相关的内容。 所以独立表空间的结构类似于下图 蓝色的表示一个组大小为 256 MB 绿色的表示一个区大小为 1M 红色的表示一个页大小为 16KB。 段 区存在的意义是尽量让页面链表中相邻的页在物理位置上也相邻这样在扫描叶子节点的大量记录时才可以使用顺序IO。 引入区是为了加快扫描叶子节点时的速度但事实上不管是叶子节点还是非叶子节点他们的页类型都是 Index, 非叶子节点间也是有链表连起来的只是我们一般用不到这些指针而已所以如果把叶子节点和非叶子节点都放在区里面扫描的性能又会大打折扣了为此InnoDB 引入了段这是一个逻辑上的概念每个索引聚簇索引或二级索引都有两个段分别用来存放叶子节点和非叶子节点。 当表中的数据很少时段会以页为单位申请存储空间这些零散的页所在的区叫做碎片区它直属于表空间。当表中的数据占了 32 个零散的页面后段会以完整的区为单位分配存储空间但之前存储在零散页面的数据并不会被移动过去。这样做的目的是尽量减少浪费。 所以段是一些零散的页面以及一些完整的区构成的集合。 区的分类 有了段后区就可以被分为下面几类 空闲区FREE完全没有被使用的区。有空闲的碎片区FREE_FRAG: 区中的部分页面被用作段的零散页面但还有空闲的页。无空闲的碎片区FUEE_FRAG: 所有页面都被用了的碎片区。完整分配给某个段的区FSEG当表中的数据占了 32 页后段会以完整的区为单位分配空间这些区就是 FSEG。 XDES Entry 为了管理这些区InnoDB 设计了一个大小为 40 字节的 XDES Entry 它的结构如下 XDES Entry 结构List Node 结构 Segment ID: 对于一个 FSEG 类型的区Segment ID 用来标识它被分配给了哪个段。List Node: 通过这个结构XDES Entry 能连成一个链表。 Prev Node Page Number, Prev Node Offset: 上一个 XDES Entry 所在的页面和在页面内的偏移通过这两个字段可以在表空间中找到上一个 XDES Entry.NextNode Page Number, Next Node Offset: 下一个 XDES Entry 。这个链表链接的是相同状态的区对应的 XDES Entry 也就是说如果一个 XDES Entry 对应的区是 FREE 状态的那么根据它的 Next 和 Prev 指针拿到的 XDES Entry 对应的区也是 FREE 状态的。如此一来不同类型区对应的 XDES Entry 就会被组织成不同的链表通过这些链表的头节点保存在固定的地方我们就可以快速获得一个需要的区或碎片页由于 FSEG 类型的区已经分配给段了所以这里的链表不包括这种类型的FSEG 类型的区会在段内链接成别的链表马上会说到。 State表示这个区的状态。Page State Bitmap: 没两位对应区中的一页的状态 00 表示这一页空闲 01表示不空闲。 有了 XDES Entry 后向表空间申请页插入新记录的的过程就是这样的了 如果表中数据不多不足 32 页就从 FREE_FRAG 链表中找到一个 FREE_FRAG 状态的区并通过 Page State Bitmap 找到一个空闲的页分配给表实际上是分配给索引或者说分配给段之后把记录插进去如果没有 FREE_FRAG 状态的区就通过 FREE 链表找到一个 FREE 状态的区将其中的一页分配给段并将这个区对应的 XDES Entry 从 FREE 链表移动到 FREE_FRAG 链表中。如果表中的数据到了 32 页就需要以区为单位给段分配空间这时只需要根据 FREE 列表找到一个 FREE 分配给段即可。 Inode Entry 类似于 XDES EntryInnoDB 为每个段设计了一个 Inode Entry 结构这个结构记录了该段的一些必要信息它的结构如下 上面说过段是由一些整块的区和一些零碎的页组成的逻辑上的结构Inode Entry 记录的就是这些信息对于段中整块的区InnoDB 将其分成了三类 FREE 区完全没有使用的区刚刚分配的。NOT_FULL 区还有空页面的区。FULL 区没有空页面的区。 这三类区对应的 XDES Entry 结构也会组成一个链表从上面的区的分类来看他们都是 FSEG 类型的Inode Entry 中的 List Base Node For FREE List, List Base Node For NOT_FULL List, List Base Node For FULL List 对应的就是这三个链表的头节点 NOT_FULL_N_USED 字段储存的就是 NOT_FULL 链表中已经使用了多少页面了。 Magic Number 字段用来标记 Inode Entry 是不是已经被初始化了值为 97937874 时表示已经初始化了确实是 Magic Number 下面的 32 个 Fragment Array Entry 每个占四字节用来存储段中 32 个零碎页的页号。 Segment ID 用来记录这个段的唯一 ID。 小结 页是分配存储空间的最小单位但页太小了在数据量特别大时如果依然以页为单位分配可能导致逻辑上相邻的两个页在物理上相隔很远这样在遍历叶子节点时就会造成大量的随机 IO为此InnoDB 规定当表中数据占用空间小于 32 页时从碎片区中以页为单位分配当超过 32 个页后就以更大的区连续的 64 个页为单位分配存储空间每个区由一个 XDES Entry 结构管理不同状态的 XDES Entry 结构通过 List Node 链接成一个链表也就看一看作是不同状态的区链成了不同的链表在分配区或碎片页时就可以直接从对应链表获取到对应的区了。 为了进一步减少随机 IOInnoDB 还引入一个逻辑上的概念 “段”每个索引对应两个段分别是叶子节点段和非叶子节点段每个段实际上是一些碎片页和一些整块的区FSEG 状态的集合每个段由一个 Inode Entry 结构管理在段里完整的区也会被分成三类每类使用单独的链表链接。 页面类型 上面说的 XDES Entry, Inode Entry 是被存储在特定的页面类型中的他们分别是 XDES 页 Inode 页 和 FSP_HDR 页 他们的结构如下 XDES 页INODE 页FPS_HDR 页 除了熟悉的 XDES Entry 和 Inode Entry 外 File Header 和 File Tialer 是所有页面共有的在索引页那已经说过剩下的就是 INODE 页的 List Node For INODE Page List 和 FSP_HDR 页的 File Space Header 了。 List Node For INODE Page List 上面说过INODE 页是表空间的第一组第一个区的第三个页里面的核心结构式 Inode Entry, 用来描述段信息但这样一页只能有 85 个 Inode Entry, 如果一张表里的段数量超过85个索引数量超过 42 时就需要额外的 INODE 页来存储这些 Inode Entry 了 根据这个 List Node For INODE Page List 字段就找到别的 INDOE 页它的结构如下 File Space Header 关于 FSP_HDR 页面前面也说过了它类似于 XDES 页面存储了本组 256 个区的信息除此之外他是表空间的第一个页面因此还存储了表空间的一些通用信息这些信息就被存储在 File Space Header 里它的结构如下 Space ID: 表空间 IDSize表空间拥有的页面数FREE Limit: 未被初始化的最小页号大于或等于该页号的区对应的 XDES Entry 都没被加入 FREE 链表, 每个表空间对应的其实是一个自增长的 ibd 文件当然可以在建表时直接指定一个非常的文件这些表空间中可能有大量未使用的区InnoDB 不会把所有空闲区一股脑的加入 FREE 链表而是会等到空闲区不够时再加一批到链表中加入到链表中的就是被初始化了反之就是未初始化。Space Flags: 一些标志字段FRAG_N_USED: 类似于 Inode Entry 中的 NOT_FULL_N_USED, 表示 FREE_FRAG链表中有多少页面被使用了。List Base Node for FREE List: 上面说 FREE 链表的根节点被保存在固定的地方就是这。List Base Node for FREE_FRAG ListFREE_FRAG 链表根节点。List Base Node for FULL_FRAG ListFULL_FRAG 链表根节点。Next Unused Segment ID: 每个段都有一个唯一 ID这个字段表示下一个可以分配的段ID。List Base Node for SEG_INODES_FULL上面说INODE 类型的页面可能有多个由 List Node For INODE Page List 连接这些 INODE 页也会依据有没有满链成两个链表SEG_INODES_FULL 和 SEG_INODES_FREE, 这个字段就是 SEG_INODES_FULL 链表的头节点。List Base Node for SEG_INODES_FREE: SEG_INODES_FREE 链表的头节点。 总结 最后祭上大图吧 [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-tgY4L5xG-1614441836399)(https://pic.stackoverflow.wiki/uploadImages/103/116/47/193/2021/02/27/22/43/16d6dfe6-2353-406b-87d0-61c9d5f24837.svg)] 系统表空间 上面介绍了独立表空间的结构它对应于数据库里的每一张表但还有一些问题没有解决比如如何确定哪张表对应哪个表空间等这就需要系统表空间一个 MySQL 服务只会对应一个系统表空间它是 MySQL 服务的第一个表空间 Space ID 为 0 记录了整个系统属性的相关信息第一个组中的前七个页面类型分别为 FSP_HDRIBUF_BITMAPSYS_insert buffer headerINODE_insert buffer rootTRX_SYS: 存储事务系统相关信息SYS_first rollback segment: 第一个回滚段信息SYS_data dictionary header: 数据字段头部信息 这里简单介绍与 Change Buffer 相关的 IBUF_BITMAP SYS_insert buffer header 和 INODE_insert buffer root 以及数据字典相关的 SYS_data dictionary header 其他字段都用于事务。 Change Buffer 其实 IBUF_BITMAP 类型的页面在独立表空间也一直出现过它实质上也是一棵 B 树当我们往表中插入一条记录时首先完整的记录会被插入到聚簇索引的叶子节点上其次还需要更新所有二级索引但这些索引随机处在表空间的不同地方每次修改这些索引可能引起许多随机 IO这会影响数据写入的效率为此当执行二级索引写入操作时如果 InnoDB 发现二级索引对应的页面没在内存中就会暂时把修改数据写到 Change Buffer 里等服务器空闲时再把数据写到二级索引对应的页里。 其中系统表空间的 SYS_insert buffer header 字段用于存储 Change Buffer 的头部信息 INODE_insert buffer root 用于存储 Change Buffer 的根节点。 数据字典 InnoDB 的数据字典保存了许多重要的元数据 包括 表对应的表空间表中有多少列每一列的类型是什么表中有多少索引索引的字段索引根节点对应的页面外键信息等…… 这些信息是为了更好的管理用户信息而存在的InnoDB 将他们放在一些内部表中比较重要的有 SYS_TABLES: 存储所有表信息SYS_COLUMNS: 存储所有列信息SYS_INDEXS: 存储所有索引xinxSYS_FIELDS: 存储所有索引对应的列信息SYS_TABLESPACES: 存储所有表空间信息…… 其中前四个表被称为四个基本表使用这四个表我们就可以获取其他系统表和用户数据了比如更具表名就可以在 SYS_TABLES 表里获取到 Table ID, 根据 ID 到 SYS_COLUMNS 就可以获取到所有列信息还可以到 SYS_FIELDS 和 SYS_INDEXS 获取到索引信息…… 具体操作要看这四张表的具体结构 其他表可以使用这四张表定位那这四张表该怎么定位呢答案是硬编码这四张表的信息被硬编码到了系统表空间的第七页上也就是 SYS_data dictionary header 关于这一页的结构就不赘述了。 需要注意的是这些内部系统表用户是不能直接访问的但 InnoDB 为了用户能更好的使用存储引擎提供了这些内部表的映射对应数据库 information_schema, 这里面有一些 INNODB 开头的表 如 INNODB_TABLES 的表结构如下 CREATE TEMPORARY TABLE INNODB_TABLES (TABLE_ID bigint(21) unsigned NOT NULL DEFAULT 0,NAME varchar(655) NOT NULL DEFAULT ,FLAG int(11) NOT NULL DEFAULT 0,N_COLS int(11) NOT NULL DEFAULT 0,SPACE bigint(21) NOT NULL DEFAULT 0,ROW_FORMAT varchar(12) DEFAULT NULL,ZIP_PAGE_SIZE int(11) unsigned NOT NULL DEFAULT 0,SPACE_TYPE varchar(10) DEFAULT NULL,INSTANT_COLS int(11) NOT NULL DEFAULT 0 ) ENGINEMEMORY DEFAULT CHARSETutf8;TABLE_ID: 表IDNAME表名FLAG有关表格式和存储特性的位级信息数据包括行格式压缩页大小如果适用以及DATA DIRECTORY子句是否与CREATE TABLE或ALTER TABLE一起使用等参考 24.32.22 The INFORMATION_SCHEMA INNODB_SYS_TABLES TableN_COLS: 表中有多少列SPACE表所属表空间 IDROW_FORMAT行格式默认为 DynamicZIP_PAGE_SIZE: 压缩页大小SPACE_TYPE: 表所属的表空间类型。可能的值包括System(系统表空间)、General(普通表空间)、Single(独立表空间)INSTANT_COLS8.0 之后的新特性表示插入的列的个数参考 MySQL8.0 - 新特性 - Instant Add Column 总结 InnoDB 的完整数据存放在聚簇索引的叶子节点上索引的一个节点就是一页为了减少随机 IO当表中的数据很多时会一次性分配连续的 64 页称为一个区每个区由一个 XDES Entry 结构管理根据区的状态这些 XDES Entry 会链成不同的链表链表头节点保存在表空间的第一个页面上除此之外为了尽可能保证叶子节点在物理内存上连续 InnoDB 把叶子节点和非叶子节点通过段分开每个段由 Inode Entry 管理。 当定位到页后InnoDB 还提供了页目录来提高页内检索速度。 MySQL 服务共有的信息被存储在系统表空间中最重要的是 InnoDB 数据字典通过它我们才可以获取到表空间中的记录。 参考 小孩子 - MySQL 是怎么运行的
http://www.zqtcl.cn/news/769886/

相关文章:

  • 德州网站网站建设广西房管局官网
  • 白石桥做网站公司seo顾问服务四川
  • 网站建设注册哪类商标十大网页设计公司
  • 网站建设的源代码有什么作用金华网站建设优化技术
  • 个人网站申请做瞹瞹嗳视频网站在线观看
  • 做网站 融资玉石网站建设的定位
  • 自己做的网站字体变成方框seo同行网站
  • 宁波网站建设培训微信小程序开发平台官网
  • 西部数码做的网站打不开哈尔滨模板建站推荐
  • 外贸网站建设流程杭州软件定制开发
  • 网站的首页面设计软文推广特点
  • 网站描述在哪里写网页设计图片怎么换
  • 深圳网站关键词优化推广做mod游戏下载网站
  • 通达oa 做网站wordpress动转换标签别名
  • 三亚学做网站培训招聘网站排名
  • 企业网站建设费用需要多少钱怎样下载建设银行信用卡网站
  • 厦门建网站公司怎么做服装外贸网站
  • 做淘宝客网站用什么程序好仿站下载工具
  • 网站地图开发国家住房和城乡建设部中国建造师网站
  • 巫山网站建设泉州市培训建设系统中心网站
  • 网站开发国内外研究背景室内设计师收入高吗
  • 深圳网站维护一般多少钱沈阳做网站黑酷科技
  • 汽车营销服务网站建设怎样申请微信公众号个人
  • 阿里云 做网站北京工程建设交易中心网站
  • 网站备案安全承诺书竞价外包推广专业公司
  • 如何做公司网站广西住建厅八大员报名网站
  • 以下不是网站开发语言的哪项工信部域名备案管理系统
  • 优化网站搭建创业项目网站建设规划
  • 温岭网站开发网站建设程序文件
  • 有什么网站可以做深圳初二的试卷练习商城网站功能