【MySQL精通系列之三】【存储引擎架构】

        为了进一步深入理解MySQL存储引擎,我们有必要了解一下存储引擎的数据存储结构,在此之前,我们得先了解下数据在文件系统中的存储。

磁盘的基本知识

        数据库的数据存储在文件系统中。文件系统是操作系统用来 明确 存储设备(常见的是磁盘,也有基于NAND Flash的固态硬盘)或分区上的文件 的方法和数据结构。磁盘上数据必须用一个三维地址唯一标示:柱面号、盘面号、块号(磁道上的盘块)。

        硬盘只是磁盘的一种,或说是经典代表,以下通过硬盘模型图讲解磁盘中的各个概念。

硬盘整体模型图

 硬盘模型图

 

磁盘重点概念

  • 盘片(platter):硬盘中承载数据存储的介质
  • 硬盘一般由多个盘片组成,每个盘片包含两个面,每个盘面都对应地有一个读/写磁头。受到硬盘整体体积和生产成本的限制,盘片数量都受到限制,一般都在5片以内。盘片的编号自下向上从0开始,如最下边的盘片有0面和1面,再上一个盘片就编号为2面和3面。
  • 磁头(head):通过磁性原理读取磁性介质上数据的部件
  • 磁道(track):当磁盘旋转时,磁头若保持在一个位置上,则每个磁头都会在磁盘表面划出一个圆形轨迹,这些圆形轨迹就叫做磁道
  • 扇区(sector):磁盘上的每个磁道被等分为若干个弧段,这些弧段便是硬盘的扇区,同一块硬盘上的扇区大小是一致的
  • "每个磁道的扇区数一样的"说的是老的硬盘,外圈的密度小,内圈的密度大(简单理解就是,磁盘存储媒介为磁性记忆材料,在内圈涂的密度高),故每圈可存储的数据量是一样的。新的硬盘数据的密度都一致,这样磁道的周长越长,扇区就越多,存储的数据量就越大。
  • 柱面(cylinder):在有多个盘片构成的盘组中,由不同盘片的面,但处于同一半径圆的多个磁道组成的一个圆柱面

物理扇区(physical sector)与逻辑扇区(logical sector)

        近年来,为了最求更高的硬盘容量,便出现了扇区存储容量为2048、4096等字节的硬盘,我们称这样的扇区为"物理扇区"。这样的大扇区会导致许多兼容性问题,有的系统或软件无法适应。为了解决这个问题,硬盘内部将物理扇区在逻辑上划分为多个扇区片段并将其作为普通的扇区(一般为512字节大小)报告给操作系统及应用软件。这样的扇区片段我们称之为“逻辑扇区”。实际读写时由硬盘内的程序(固件)负责在逻辑扇区与物理扇区之间进行转换,上层程序“感觉”不到物理扇区的存在。

        逻辑扇区是硬盘可以接受读写指令的最小操作单元,是操作系统及应用程序可以访问的扇区,多数情况下其大小为512字节。我们通常所说的扇区一般就是指的逻辑扇区。物理扇区是硬盘底层硬件意义上的扇区,是实际执行读写操作的最小单元。是只能由硬盘直接访问的扇区,操作系统及应用程序一般无法直接访问物理扇区。当要读写某个逻辑扇区时,硬盘底层在实际操作时都会读写逻辑扇区所在的整个物理扇区。

磁盘容量计算

  • 旧式——非ZBR区位记录(不同磁道扇区数相同)
    存储容量 = 磁头数 × 磁道(柱面)数 × 每道扇区数 × 每扇区字节数
    比如上图最右边硬盘容量:6 * 7 * 12 * 512 = 258048 byte
  • 新式——ZBR区位记录(不同磁道扇区数不同)

块(Block)/簇(Cluster)

块/簇两者指的是同一个逻辑上的概念,只是在Linux与Windows中的称呼不同。

  • 块/簇 是操作系统中最小的逻辑存储单位。操作系统与磁盘打交道的最小单位是块/簇。
  • 在Windows下如NTFS等文件系统中叫做簇;在Unix和Linux下如Ext4等文件系统中叫做块(block)。
  • 每个簇或者块可以包括2、4、8、16、32、64…2的n次方个扇区。

块/簇 用来干什么的

磁盘的最小单位是扇区,操作系统使用的是 块/簇 作为IO的基本单位。

  • 读取方便:扇区容量小,数据多会加大寻址难度。操作系统将相邻的扇区组合一起形成块,再对块整体操作
  • 分离对底层的依赖:操作系统忽略对底层物理存储结构的设计。通过虚拟出来磁盘块的概念,在系统中认为块是最小的单位

扇区是对硬盘而言,块是对文件系统而言,出于不同的需要。

查看块/簇的大小

不同文件系统中block的大小不一样。

Windows:(使用管理员命令提示行)
fsutil fsinfo ntfsinfo E:

Linux:
stat /home | grep "IO Block"

如下所示,Windows下E盘的Cluster的大小为4Kb大小,如下所示:

页(Page)

        操作系统经常与内存和硬盘这两种存储设备进行通信,类似于“块”的概念,都需要一种虚拟的基本单位。与内存操作,是虚拟一个页的概念来作为最小单位。与硬盘打交道,就是以块为最小单位。

扇区、块/簇、页的关系

  • 扇区: 硬盘的最小读写单元
  • 块/簇: 是操作系统针对硬盘读写的最小单元
  • 页: 是内存与操作系统之间操作的最小单元。
  • 扇区 <= 块/簇 <= 页

MySQL的InnoDB数据存储结构

        MySQL的InnoDB数据存储结构可以划分为逻辑存储结构和物理存储结构。

前置:数据库磁盘读取与系统磁盘读取

  • 系统从磁盘中读取数据到内存时是以磁盘块(block)为基本单位,位于同一个磁盘块中的数据会被一次性读取出来。
  • InnoDB存储引擎中有页(Page)的概念,页是数据库管理磁盘的最小单位,InnoDB存储引擎中默认每个页的大小为16kb,每次读取磁盘时都将页载入内存中。
  • 系统一个磁盘块的大小空间往往没有16kb这么大,因此InnoDB每次io操作时都会将若干个地址连续的磁盘块的数据读入内存,从而实现整页读入内存。

物理存储结构

        从物理意义上来看,InnoDB表由共享表空间、日志文件组(更准确地说,应该是Redo文件组)、表结构定义文件组成。若将innodb_file_per_table设置为on,则每个表将独立地产生一个表空间文件,以ibd结尾,数据、索引、表的内部数据字典信息都将保存在这个单独的表空间文件中。表结构定义文件以frm结尾,这个是与存储引擎无关的,任何存储引擎的表结构定义文件都一样,为.frm文件。

逻辑存储结构

        InnoDB存储引擎的逻辑存储结构和Oracle大致相同,所有数据都被逻辑地存放在一个空间中,我们称之为表空间。表空间又由段、区、页组成。1 extent = 64 pagesInnoDB存储引擎的逻辑存储结构大致如图所示。

表空间(tablespace)

        表空间可以看做是InnoDB存储引擎逻辑结构的最高层,所有的数据都是存放在表空间中。默认情况下InnoDB存储引擎有一个共享表空间ibdata1,即所有数据都放在这个表空间内。如果我们启用了参数innodb_file_per_table,则每张表内的数据可以单独放到一个表空间内。

        对于启用了innodb_file_per_table的参数选项,需要注意的是,每张表的表空间内存放的只是数据、索引和插入缓冲,其他类的数据,如撤销(Undo)信息、系统事务信息、二次写缓冲(double write buffer)等还是存放在原来的共享表空间内。这也就说明了另一个问题:即使在启用了参数innodb_file_per_table之后,共享表空间还是会不断地增加其大小。

段(segment)

        表空间是由各个段组成的,常见的段有数据段、索引段、回滚段等。

        InnoDB存储引擎表是由索引组织的(index organized),因此数据即索引,索引即数据。InnoDB采取B+树作为存储数据的结构,数据段即为B+树的叶节点(上图的leaf node segment),索引段即为B+树的非叶子节点(上图的non-leaf node segment)。

        InnoDB存储引擎对于段的管理是由引擎本身完成。

区(extent)

        一个区是由64个连续的页组成的,每个页大小为16KB,即每个区的大小为1MB。对于大的数据段,InnoDB存储引擎最多每次可以申请4个区,以此来保证数据的顺序性能。

        在我们启用了参数innodb_file_per_talbe后,创建的表默认大小是96KB,新建的InnoDB表就是一个区。区是64个连续的页,那创建的表的大小至少是1MB才对啊?其实这是因为在每个段开始时,先有32个页大小的碎片页(fragment page)来存放数据,当这些页使用完之后才是64个连续页的申请。

create table innodb_table(
	id int primary key
)engine=innodb default charset=utf8;

 

页(page)

        每个页大小为16KB,页是InnoDB磁盘管理的最小单位,整页整页的读取。

        InnoDB中主要的页类型:

  • 数据页(BTreeNode)
  • Undo页(undo Log page)
  • 系统页(System page)
  • 事务数据页(Transaction SystemPage)

  • 0-38:页头占据38位字节,页面id(32位的整数),页面类型,以及两个分别指向前一个page和后一个page的指针(page是一个双向列表)等信息
  • 38-16376:不同的类型页所含的数据不同,这部分空间包含系统记录(SystemRecord)和用户记录(UserRecord),我们表中的一条条记录就放在UserRecord部分
  • 16376-16384:页面结束标识

        由页组成的链表,页之间是双向列表,页里面的数据是单向链表,这种结构组成了主键索引B+树,组成了叶子节点数据。

 

定位一条表记录的过程

select * from user where id = 29

        这里id是主键,我们通过这棵B+树来查找,首先找到根页,你怎么知道user表的根页在哪呢?

        其实每张表的根页位置在表空间文件中是固定的。系统经过解析sql语句,首先从找到user表的跟页面(一个表通常需要多个页面组成,跟页面就是起始页),层级遍历非叶子节点页(索引)读取到key值为29的指针(遍历非叶子节点的过程随着节点的遍历会将一个或多个页加载到内存),最后到指针指向的叶子节点所在的页中,然后遍历找出该条记录。

        如果使用了二级索引则先读取二级索引page遍历这个二级索引,找到装有主键信息叶子节点page页,遍历找到该主键。然后再根据主键索引寻找到该条记录。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值