本文主要是对InnoDB的逻辑存储结构进行学习。
mysql支持很多存储引擎,使用show engines
可以查看,如下图所示
其中InnoDB是我们实际工作中最常接触到的存储引擎。
InnoDB存储引擎,数据被放在表空间(tablespace
)中,表空间又分为段(segment
)、区(extent
)、页(page
)。
默认情况下InnoDB存储引擎有一个共享表空间ibdata1
,即所有的数据都放在这个表空间内。当参数innodb_file_per_table
开启的时候,每个表的数据就会单独放到一个表空间内。
例如我有一个数据库mytestdb
,里面有一个表user_info
。那么在mysql存放数据的路径里面,就有会一个mytestdb
文件夹,里面有user_info.frm
和user_info.ibd
两个文件。
注意:每个表的表空间里面存放的是数据、索引、插入缓冲Bitmap页,其他的数据(例如undo log、系统事务信息等)还是存放在原来的共享表空间ibdata1
里面,所以即使innodb_file_per_table
已开启,共享表空间ibdata1
还是会变大。
表空间由各个段组成,常见的段有数据段、索引段、回滚段等。
区是由连续页组成的空间,每个区的大小都是1MB
。为了保证区的连续性,InnoDB存储引擎会一次从磁盘申请4~5个区。
页是InnoDB磁盘管理的最小单位,每个页默认的大小是16KB
,所以一个区有64个连续的页。可以通过参数innodb_page_size
来设置页的大小。常见的页的类型有:数据页、undo页、系统页、事务数据页…………
数据页的结构如下图所示:
可以看到InnoDB数据页里面有以下部分:
- File Header :里面是记录的一些头信息。
- 例如上一个页
FIL_PAGE_PREV
、下一个页FIL_PAGE_NEXT
。(所以页和页之间是双向链表) - 例如页的类型
FIL_PAGE_TYPE
,可以是数据页,也可以是索引页或其他类型,根据取值来进行区分 - …………
- 例如上一个页
- Page Header :是记录数据页的状态信息
PAGE_N_DIR_SLOTS
是在Page Directory
页目录中的槽数PAGE_N_RECS
是该页中记录的数量PAGE_LAST_INSERT
是最后插入记录的位置- …………
- Infimum和Supremum :是每个数据页中都有的两个虚拟的行记录。这两个在页创建的时候就有了,而且在任何情况下都不会被删除。
- Infimum是比该页中最小的记录还要小的记录
- Supremum是比该页中最大的记录还要大的记录
- User Record :是实际存储的记录内容
- 行与行之间是链表结构
- Free Space :是空闲空间
- 该部分也是链表结构。
- 当一条记录被删除之后,它的空间就会被加入空闲链表中
- Page Directory :是一个稀疏目录。
- InnoDB查找在具体的数据页里面查找某条记录的时候,现将数据页载入内容,然后通过Page Directory二分查找找到大致的位置,然后通过链表结构(即每个行的
next_record
标志位来找到下一条)来查找。
- InnoDB查找在具体的数据页里面查找某条记录的时候,现将数据页载入内容,然后通过Page Directory二分查找找到大致的位置,然后通过链表结构(即每个行的
- File Trailer :是为了检测页是否已经完整写入磁盘用的,可以用来保证页的完整性。