之前的8月15号的文章中,对于Innodb的表空间做了一些介绍,当时重点介绍了表空间中最主要的两种类型:独立表空间和系统表空间。今天我们展开说说独立表空间的内容。
我们知道,表空间中包含数据页和索引页,这些数据页和索引页的数量很多,为了更好的管理这些16k大小的页面,在Innodb存储引擎中,提出了"区"的概念,那么什么是区呢?
区
我们知道数据页的大小是16kb,它是内存和磁盘交互的最小单位,对于16kb的数据页来讲,64个数据页,就是一个区,英文名称是extent,这样,不难计算出一个区的数据大小是1024kb,也就是1M的数据。
组
这里将256个区又称之为一个组(group),很容易计算出来一个组的数据量大小是256M,但是这里需要注意,每个组中的第一个区中的前几个页面是这个组特有的,是用来描述这个组内的信息特有的页面,不能理解为普通的数据页。
为什么引入区这个概念呢,之前在索引一章说过,索引在分配空间的时候是按照数据页来进行分配的,然后相邻的数据页之间用双向链表连接,数据页在磁盘中不保证是相邻的。我们考虑这样一种情况,索引中的数据页距离都非常非常远,需要使用链表中的指针中的位置偏移量去找下一个数据页的真实位置,这样随着数据量的增长,链表查找数据页的场景类似一种随机的磁盘IO操作,难免影响操作性能。引入了区的概念之后,当我们为索引分配空间的时候,innodb就可以按照区为单位进行分配空间,这样能够保证数据页和索引页的位置比较近,搜索起来比较方便,可以消除大部分随机IO的情况。除此之外,innodb还会将索引中的叶子节点和非叶子节点分别放在两个不同的区中,这样在进行数据记录的范围查找,也就是聚集索引叶子节点的范围查找的时候,会提高查找的性能。而我们把叶子节点所在的区和非叶子节点所在的区称之为两个"段",英文名称称之为segment,也就是说,一个聚集索引会生成两个段,一个叶子节点段,一个非叶子节点段。但是需要注意的是,段在表空间中,其实并不对应某一个连续的物理区域。
到这里,可能需要一张图来说明一下逻辑结构:
其中右下角的图是使用了之前索引一文中的图,不记得了可以往前翻翻看。
截止现在,我们大概了解了独立表空间、段、区、组、数据页的基本概念了。系统表空间和独立表空间基本上是类似的,因为系统表空间是整个MySQL中所有表公用的一个数据页池子,所以它里面会额外记录一些有关整个MySQL服务的信息。除此之外,系统表空间中的extent 1和extent 2这两个区的128个页面被称之为doublewrite buffer,也就是我们常说的双写缓冲区。关于innodb存储引擎的双写,之前6月5号的文章中有讲过,为了防止大家忘记,这里我把当时画的图搬出来共大家参考:
两次写的概念当时描述如下:
我们看到的doublewrite分为两个部分,其中一个是内存中的,大小为2MB,另外一部分是物理磁盘的共享表空间中的,也就是ibdata文件中的连续的128个数据页,128*16K,也就是2MB,在对缓冲池的脏数据进行刷盘的时候,并不会直接写到磁盘中,而是先将数据复制到内存中的doublewrite的缓存中,之后通过缓存,再分两次,每次1MB的写入共享表空间的物理磁盘上。完事儿之后然后立马同步磁盘。这样,一份数据就在磁盘上有两个副本。
忘记的同学可以回看。时间关系,今天的内容就到这里吧。