title: MySQL 是怎样运行的(二)——数据库文件系统
date: 2019-3-18 12:34:39
tags: [mysql]
categories: 掘金小册
keywords: mysql
photos:
MySQL 是怎样运行的(二)——数据库文件系统
查看数据目录:SHOW VARIABLES LIKE 'datadir';
区分mysql安装目录与数据目录
表在文件系统的表示
1.表结构,存储在 表名.frm 中。
2.数据,根据引擎不同,方式不同
InnoDB的表数据存储
InnoDB其实是使用页为基本单位来管理存储空间的,默认的页大小为16KB。
对于InnoDB存储引擎来说,每个索引都对应着一棵B+树,该B+树的每个节点都是一个数据页,数据页之间不必要是物理连续的,因为数据页之间有双向链表来维护着这些页的顺序。
InnoDB的聚簇索引的叶子节点存储了完整的用户记录,也就是所谓的索引即数据,数据即索引。
InnoDB的表空间(文件空间)
- 是抽象的概念,对于一个或多个文件,包含若干个页,具有不同类型。
系统表空间 - 大小默认12M,会动态扩展,可初始修改大小。
- 只有一份,Mysql版本5.5.7到5.6.6,数据都默认存储到系统表空间
独立表空间 - 5.6.6以后,InnoDB默认会给每个表单独创建独立表空间。文件名
表名.ibd
-
表名.frm
存储表结构,表名.ibd
存储数据和索引。 - 可初始设置不使用独立表空间,也可将一个表的空间表示(独立↔系统)
其他表空间
通用表空间、undo表空间、临时表空间
MyISAM的储存表示
- test.frm 表结构
- test.MYD 数据文件
- test.MYI 索引文件
视图的表示
视图是虚拟的表,一条查询的结果集。储存视图的时候是不用存数据的,只需要存储其数据结构,会被储存到对于数据库下,视图名.frm
文件。
其他文件
服务器进程文件:进程id
服务器日志文件:各种日志
默认/自动生成的SSL和RSA证书和密钥文件:用于C/S通信
文件系统对DB的影响
1.DB名与TABLE名不得超过文件系统允许的最大长度
2.特殊字符:在上述两名字中,存在除数字和拉丁字母以外的所有字符,都映射成@编码值,如’test?'表会创建,‘test@003f.frm’
3.数据文件和索引文件的大小都受限于文件系统
Mysql数据库介绍
- mysql 核心数据库,存储用户账户和权限和其他重要信息
- information_schema 描述信息,元数据
- performance_schema 状态信息,用于监控mysql
- sys 通过视图结合infor_schema和perfor_schema表,用于展示
InnoDB的表空间
抽象概念,可想象成包含若干个数据页的池子
独立表空间
区(extent:程度,范围) 与 组
作用:表空间中页太多,使用区便于管理
- 页大小16kb,连续的64个页就是一个区,默认1MB
- 每256个区(也是连续吗?)被分为一组,256MB
第一个组开头3个页类型是固定的,比较特殊,分别是:
- FSP_HDR:描述表空间的一些属性,每个表空间开头唯一的页
- IBUF_BITMAP: 存储本组关于INSERT BUFFER信息
- INODE:
除第一个组外,每个组开头有2个页类型是固定的
- XDES:extent descriptior,用于登记本组256个区的属性
- IBUF_BITMAP
区的作用:
场景:当数据量很大,页有很多的时候,N次插入后。通过双向链表连接的两个逻辑上的页,其物理距离可能相差很远。若使用范围查找,只需找到最左和最右记录,而中间的记录通过双向链表扫描,使用的是随机I/0(很慢),我们希望其物理位置也最好相邻,可使用顺序IO
区: 物理位置上连续的64个页,在数据量大的时候,分配空间按照区(1MB)分配而不是页(16KB),升至数个区的分配。(好处:减少随机I/0,坏处:空间预分配的浪费,以空间换时间)
段:存放叶子或非叶子节点 的区(和零散页)的集合
因为顺序查找,是同一层的双向链表间的查找,我们不希望 叶子节点和非叶子节点混到一起了。所以一个索引有
- 叶子节点段 (叶子节点 区集合)
- 非叶子节点段 (非叶子节点 区集合)
场景:若数据少,岂不是一个索引要一个区,1MB叶子段,1MB非叶子段?这么浪费?所以有了碎片区
碎片区(fragment)
一个区中,不是所有页都是为了储存同一个段。而是有的页是段A,有的是段B。
- 在刚开始向表中插入数据的时候,段是从某个碎片区以单个页面为单位来分配存储空间的。
- 当某个段已经占用了32个碎片区页面之后,此段就会以完整的区为单位来分配空间
区的分类
- FREE 空闲的区
- FREE_FRAG 有剩余空间的碎片区
- FULL_FRAG 没有剩余空间的碎片区
- FSEG 附属于某个段的区
可以理解将碎片区理解为:放置了不同段页面的区?
XDES页 与链表
- Segment ID :被分配给哪个段,不属于则无
- List Node:用于表示XDES链表,记录上一或下一个区的XDES指针
- State:标注了区的类别(四种)
- Page State Bitmap:用于表示页的使用状态
插入数据(XDES Entry链表)
当段中数据较少时,插入过程使用的是表空间链表
- 查看是否有FREE_FRAG碎片区,有则插入数据
- 否则申请FREE空闲区,并将其状态变为碎片区
- 直到将碎片区变为FULL_FRAG
当段中数据已经占满32个零散的页,再使用表空间链表遍历,效率就低了,
- 通过段中的,FREE链表,申请完整的区(空闲区)
几种用于查找的列表
每个区的头部 都有XDES Entry,通过它能将同种类别的区连接成链表。便于查找
隶属于表空间的链表
- FREE链表
- FREE_FRAG链表
- FULL_FRAG链表
隶属于 段 的链表
- FREE链表:同一个段中的 FREE区
- NOT_FULL链表:同一个段中,仍然有碎片空间的区组成
- FULL链表:同一个段中,没有空闲空间的区组成
汇总:每个索引有两个段(叶子段,非叶子段),每个段需要三种类型页链表(FREE,NOT_FULL,FULL),另外有三个隶属于表空间的链表。
基节点:用于存放这些链表的信息(头节点位置,尾节点位置,节点数)
段的结构
段虽然是逻辑概念,但是每个段都有一个INODE Entry记录段的信息
- Segment ID 段号
- NOT_FULL_N_USED 记录NOT_FULL链表中使用了多少页面,用于定位
- 三种链表的表头
- 魔数:用于检测初始化
- 段中 零散的页,记录其页号