如果你不了解InnoDB的存储逻辑,可能你并不是真正搞懂MySQL

InnoDB存储逻辑

InnoDB存储引擎的逻辑存储是将所有的数据都逻辑的存放在一个空间中,我们称之为表空间(tablespace)。表空间又是由段(segment)、区(extent)、页(page)组成。如下图

 

表空间(Tablespace)

表空间是InnoDB存储引擎逻辑结构的最高层,所有数据都放在表空间ibdata1里。在MySQL5.6之后默认每张表单独一个表空间,通过innodb_file_per_table参数来控制,默认为1。需要注意的是,即使每张表都有一个单独表空间,但是这个表空间的内存只存放数据、索引和插入缓冲,对于其他数据,如undo log、系统事物信息,二次写缓冲等还是存放在原来的共享表空间

段(Segment)

表空间是由多个段组成的,常见的有数据段、索引段和回滚段。因为InnoDB存储引擎是索引组织表,所以数据段就是B+树的叶子节点。索引段就是B+树的非索引节点。

区(Extent)和页(page)

区是由多个连续的页组成,页是InnoDB磁盘管理的最小单位,默认每个页的大小为16K。而任何情况下每个区都是固定大小1MB。

按照这样计算,一个区最多可容纳64个页,一个页可以容纳2~N个行,行的数量就取决于它的大小。(为什么是2~N?因为InnoDB要求页至少要有2行)。

页的内部原理

因为InnoDB是索引组织表,所以行记录会按照主键来排序。当你插入数据的时候,如果数据大小刚好能够放进页中的话,那么此时就按顺序将页填满。如果当前页满,那么改行记录就会被插入到下一页中。

 

如上图,当id为5的数据要插入到页5时候发现要满了,此时无法插入。那么根据B树的特征,每个叶子都有指向下一条记录的页的指针。那么此时数据5就会插入到页6上面。

页合并

当你删除一行记录的时候,实际上记录并没有被物理删除,而是被标记(flaged)为删除。如果之后再插入该位置的记录时,会复用这个位置。但是磁盘文件并不会缩小。

 

你可能会有疑问,如果磁盘文件不会缩小,那我们表空间不就越来越大了?

此时就需要表合并了,当删除记录达到MERGE_THRESHOLD(默认页体积的一半),那么InnoDB就会开始寻找最近的页(前或后)看看是否可以将两个页合并成一个页,以优化空间。

 

页分裂

前面提到,页如果填满了之后,会根据地址找到下一页存放新纪录。那么此时会不会存在一种特殊情况当前页满了,而下一页也满了如下图,那么此时怎么办?

 

还记得之前提起吗?B+树每一层都是一个双向链表,链表我们是怎么插入节点的,是不是新创建一个节点,然后改变节点next的指针,从而实现了插入。InnoDB的做法也类似:

1:创建新页7

2:判断当前页可以从哪里分裂

3:移动记录行

4:重新定义页之间的关系

因为还是按照原定的顺序排列的,即使物理上来讲页是乱序的,但是逻辑上还是连续的。

操作提示

无论是页分裂还是合并,都会锁表,在操作频繁的系统中这可能会是个隐患。所以我们应该尽可能的减少页的分裂和合并。

首先再选择ID的时候,尽量自增,自增的主键可以更好的减少合并次数。再插入时也尽量避免随机插入选择顺序插入,顺序插入的话索引是紧凑的,同样会减少页的分裂几率

最后,如果感觉对你有帮助就来个二连吧:关注、点赞!

猜你喜欢

转载自blog.csdn.net/qq_25448409/article/details/105912119