作者:Mayank Prasad 译:徐轶韬
在InnoDB中,用户定义的表及其对应的索引数据存储在扩展名为.ibd的文件中。表空间有两种类型,常规(或共享)表空间和独立表空间文件。对于共享表空间而言,来自多个不同表及其对应索引的数据可以保存在单个.ibd文件中。而对于独立表空间,单个表的数据及其索引保存在一个.ibd文件中。
这篇博客文章将详细讨论这些.ibd文件中的空间管理。
.IBD文件
这些文件通常位于数据目录中。让我们尝试创建一个表test.t1。
CREATE TABLE test.t1 (c INT) engine=InnoDB;
$ cd <PATH_TO_DATA_DIR>/test
$ ls
t1.ibd
上面是独立表空间文件,即与表t1相关的表和索引数据将驻留在此文件中。
TABLESPACE
独立表空间的名称与文件/表名称相同,即上面表t1的表空间名称为t1。如果它是使用名称my_tablespace创建的常规(或共享)表空间,则该表空间名称将是 my_tablespace ..
表空间使用唯一的ID标识,称为表空间ID。
PAGES
表空间文件由固定大小的页组成。不同类型的页可用于不同目的。我们将在接下来的部分中详细介绍这些内容。在此只需记住,表空间文件是多个固定大小的页的集合。
EXTENTS
区段是表空间内连续页的集合。区段大小为1 MB。如果页大小为16Kb,则一个区段中可能有64页。
因此,我们再次查看表空间文件,它是区段的集合。
HEADER PAGE
表空间的元数据信息没有单独的存储。它存储在同一文件的页头(始终为0页)。现在让我们详细了解一下。
FREE FRAGS LIST:
区段链接列表的基节点指针,这些区段具有“单独”分配的页。此列表包含具有至少一个可用页分配的范围。
FULL FRAGS LIST:
区段链接列表的基节点指针,这些区段具有“单独”分配的页。此列表不包含可用页分配的范围。
FREE LIST:
范围自由分配的链接列表的基本节点指针。该列表的范围可以分配给文件段(稍后描述),也可以分配给空闲片段列表。
XDES Entries:
表空间中第一组区段的区段描述条目(稍后描述)。
EXTENT DESCRIPTOR PAGE (XDES PAGE)
区段是页的集合。我们需要存储与属于某个区段的页相关的一些元数据信息。为了存储该信息,我们使用“ 区段描述页”。
对于16K大小的页,一个XDES条目(稍后描述)的大小为40字节,用于提供有关64页的元数据信息。为了易于实现,一个XDES页条目所覆盖的页数等于页大小。基于此,可以很容易地找到每个页大小的XDES页中XDES条目的数量。
随着表空间的增加(添加了更多数据),将分配更多的数据块(更多的页)。一旦总范围的数量大于XDES页可以跟踪的范围,就会分配一个新的XDES页,该页将用于跟踪下一组范围。
注意:第一组区段的页头用于存储XDES条目。
下图描述了一个区段描述页和各个XDES条目。
注意: LIST NODE中的上一个和下一个指针指向列表中的上一个/ 下一个区段:
相关的数值!
一个区段大小= 1 MB
一个页大小= 16 KB
一个区段中的总页数= 64页
一个XDES页中的XDES条目总数= 256
一个XDES页中可以覆盖的区段总数= 256
一个XDES页中可以覆盖的总页数= 16384
因此,一旦表空间大小超过16384页,我们需要分配一个新的XDES页以保留更多数据区(待分配)。
INODE PAGE
这些页保留有关文件段(FSEG)的信息。因此,在进入INDOE页条目之前,让我们了解一下什么是文件段。
FILE SEGMENT
文件段是一个逻辑单元,是页和区段的集合。下图描述了文件段的高级别逻辑(非物理)视图。
注1: FRAG ARRAY中的页属于一个区段,该区段是FRAG_FULL / FRAG_FREE列表的一部分(即,文件段ID为0),并保留在表空间页头中。如前所述,这些区段中的页被许多段共享。如下图所示:
注2:当区段变为空闲(即不再有已使用的页)时,它不会移动到“文件段”的“FREE ”列表中。相反,它将移至在表空间级别维护的FREE列表。
问:为什么我们需要文件段?
答:这是为了简化页管理。一旦删除文件段,就要释放所有区段和页。
随着表的增长,它将在每个文件段中分配各个页,直到文件段数组变满为止,然后切换到一次分配1个区段,最终切换到一次分配4个区段。
INODE PAGES(重新访问)
现在,让我们回到INODE页。INODE页保留文件段的条目,即INODE页中的每个条目代表一个文件段。上面描述的图X(在其中描述了文件段的高级别视图)实际上是INODE页中的条目,被称为“INODE File Segment entry”。让我们再来看一看:
问:索引中如何使用文件段?
答: InnoDB中的每个索引(B +树)使用两个文件段。
FSEG HEADER是存储这两个文件段INODE条目信息的位置。从这些条目中,我们查询INODE页以找到相应的文件段信息。
注意:由于索引只有一个LEAF和一个NON-LEAF段,因此仅使用根页的FSEG HEADER存储这些信息。B树中的其余页,FSEG HEADER填充为0。
杰里米·科尔(Jeremy Cole)在他的博客中给出的一个很好的说明性示例:
“例如,在一个新创建的表中,唯一存在的页将是根页,它也是一个叶子页,但是存在于“内部”文件段中(这样以后就不必移动它了) 。“叶”文件段INODE列表和片段数组将全部为空。“内部”文件段INODE列表将全部为空,并且单个根页将在片段数组中。”
摘要
当我们创建/删除索引时,它们如何工作?
如上所述,一旦创建索引(即至少创建了根页),就会为该索引分配两个文件段。一个用于叶子页,到目前为止没有分配页,一个用于非叶子页,将仅分配一个页即根页。
随着索引大小的增长(即B树的增长),
从根页删除索引后,我们将知道两个文件段。我们继续将这两个文件段中的所有区段标记为空闲。
感谢您使用MySQL!
本文分享自 MySQL解决方案工程师 微信公众号,前往查看
如有侵权,请联系 cloudcommunity@tencent.com 删除。
本文参与 腾讯云自媒体同步曝光计划 ,欢迎热爱写作的你一起参与!