前面我们说了:
- mysql数据库目录,建立mysql数据库和表,会在文件系统下建立同名的目录或者文件,所以mysql取名和文件大小是受文件系统限制的。
- 数据库会生成一个文件存储数据库的结构,表也会建立文件.frm存储表的结构,比如字符集,行格式,而innoDB存储因为聚簇索引的索引即数据,所以数据和索引会存在同一个文件,mysql5.6.6之前默认在系统文件,5.6.6之后在独立的文件,这个文件是.ibd文件。而myISAM表会有两个不同的文件,一个存储索引,一个存储数据。
- 视图也比较特殊,因为我们知道视图实际指向是表的本身,所以建立视图不会建立数据文件,只会生成同名的.frm结构文件。
Mysql数据目录(3)---表数据结构myISAM(二十六)
InnoDB表空间
我们都知道innoDB存储数据是通过页来存储的,每个页大概16kb,而每个节点多属于一个数据页fil_page_index,又叫索引页,为了不同的设计目的,还有若干种其他的页面类型,为了方便大家阅读下面的文章,我在列举一次:
- fil_page_type_allocated:最新分配,还没使用。
- fil_page_undo_log:undo日志。
- fil_page_inode:段信息节点。
- fil_page_ibuf_free_list:insert buffer空闲列表。
- fil_page_ibuf_bitmap:insert buffer 位图。
- fil_page_type_sys:系统页。
- fil_page_type_trx_sys:事务系统数据。
- fil_page_type_fsp_hdr:表空间头信息。
- fil_page_type_xdes:扩展描述。
- fil_page_type_blob:blob页。
- fil_page_index:索引页,数据页。
然后页都会有通用部分,每个页百分百都有file header 和file trailer,剩余的中间部分可能不同,file trailer的作用是在数据刷新到磁盘时候,效验和和lsn值验证是否和头部的效验和lsn值相同。
数据存着区分为真实数据和额外数据,额外数据就是为了提高效率,描述真实数据的数据,比如变长字段长度列表,null值列表,头部信息,头部信息里面有delete_mark标记当前数据是否被删除,变长字段长度列表存储的是varchar,bolb等数据,如果字符集指定的是gbk,utf这种变长字符集,char也会存储在变长字段长度列表,如果是asicc则不会,null值主要放空数据,剩下的就是真实数据,真实数据列表如果超过他的存储值,就会把真实数据放到新的页里,这时候真实数据列表存储的就是一部分真实数据,一部分指定到页的页码主键值,比较级compact和dynamic不同的是,compact真实数据列表存储的是一部分页码主键,一部分真实数据,而dynamic存储的全部都是指向存储真实数据页的页码主键。
这里再回顾一下file header组成:
- fil_page_space_or_chksum:页的效验和。
- fil_page_offset:页号。
- fil_page_prev:上一个页的页号,因为所有的页存储的物理位子不在一起,和下面的fil_page_next吧所有的页通过主键连接起来组成双向链表。
- fil_page_next:下一个页的页码。
- fil_page_lsn:页码被最后修改时对应日志序列的位子。(Log Sequence Number)
- fil_page_type:页面类型。
- fil_page_file_flush_lsn:仅在系统空间的一个页定义的数据,代表文件被刷新到对应lsn的值。
- fil_page_arch_log_no_or_space_id:页面属于哪个空间。
着重注意几点:
- 表空间每个页都有对应的页号,也就是fil_page_offset,唯一值,这个值由四个字节组成,也就是32个比特位,所以表空间最多存储2的32次方个页,如果按16kb每页,则有64TB的数据可以存储。表空间的第一个页fil_page_offset页号是0,以后的依次为1,2,3.。。。
- Fil_page_prev和fil_page_next是可以吧页组成双向链表的,所以他们在物理结构上不用按物理顺序存储,这两个字段在数据页非常重要,一般其他页类型不用这两字段。
- Fil_page_type:代表不同页的类型,比如数据页就属于0x45bF。
回忆了那么多,我们现在进入正题,我们知道表存储的空间结构主要分为独立表空间结构和系统表空间结构。
独立表空间结构
区(extent)的概念
表空间的页存储数据有64TB,实在太多了,怎么才能保证高效查询呢,于是mysql设计出了区(extent)这个概念。对于16kb的页来说,连续64个页就是一个区,也就是说一个区大概1MB的数据,不论是系统表空间还是独立表空间,都是区组成,每256个区被划分为一个组,所以一个组大概是256MB。(温故知新:前面说的一个单独的页也是因为里面数据太多,提高查询效率,页里的数据用主键连接的单向链表组成,然后又分为不同的槽点,最小的槽点就放一个最小值,最大槽点放5~8个值,其余槽点放1~4个值,查询时候先找到对应的槽点,然后在槽点里吧当前槽点的所有数据从小到大遍历一遍)
所以由上可以知道,如果每256个区为一组的话:
- Extent0~extent255为一组,
- extent256~extent511为一组,
- extent512~entent767为一组。
而每一组的最开始几个页都是固定好的:
第一组extent0~extent255,前三个页的类型是固定的,分别是:
- Fil_page_type_fsp_hdr类型:表空间头部信息。这个页主要记录整个表空间的一些属性和本组所在区的属性(也就是extent0~extent255的属性),整个表空间也只有一个fil_page_type_fsp_hdr类型页面。
- Fil_page_ibuf_bitmap类型:insert buffer位图。这个页面存储的是本组区所有页面关于insert buffer信息。后面详细解读。
- Fil_page_inode类型:段信息节点。这个页面存储着许多称为inode的数据。后面详解。
而从第二组开始,前面前两个页的类型都是固定的:
- fil_page_type_xdes类型:扩展描述。全称extent descriptor,用来登入本组256个区的属性,和第一组的fil_page_type_fsp_hdr类型的页类似,但第一组的fsp_hdr还额外存储着一些表空间的整体属性,所以一个表空间只有一个fil_page_type_fsp_hdr文件。
- fil_page_ibuf_bitmap类型:和第一组一样,存储本组所有区所有页面的insert buffer信息。