mysql表空间预估_MYSQL实战优化——数据页、表空间

数据页结构

经过前面的介绍现在我们都知道,一行一行的数据是存放在数据页里的,所以接下来我们该分析一下数据页的结构了。之前介绍过,每个数据页,实际上是默认有16kb的大小,那么这16kb的大小就是存放大量的数据行吗?明显不是的,其实一个数据页拆分成了很多个部分,大体上来说包含:

math?formula=%5Ccolor%7Bgreen%7D%7B%E6%96%87%E4%BB%B6%E5%A4%B4%E3%80%81%E6%95%B0%E6%8D%AE%E9%A1%B5%E5%A4%B4%EF%BC%8C%E6%9C%80%E5%B0%8F%E8%AE%B0%E5%BD%95%E5%92%8C%E6%9C%80%E5%A4%A7%E8%AE%B0%E5%BD%95%E3%80%81%E5%A4%9A%E4%B8%AA%E6%95%B0%E6%8D%AE%E8%A1%8C%E3%80%81%E7%A9%BA%E9%97%B2%E7%A9%BA%E9%97%B4%E3%80%81%E6%95%B0%E6%8D%AE%E9%A1%B5%E7%9B%AE%E5%BD%95%E3%80%81%E6%96%87%E4%BB%B6%E5%B0%BE%E9%83%A8%7D文件头、数据页头,最小记录和最大记录、多个数据行、空闲空间、数据页目录、文件尾部。下面我们来看一张图:

96a1b4ccded1

datapage2.jpg

其中文件头占据了38个字节,数据页头占据了56个字节,最大记录和最小记录占据了26个字节,数据行区域的大小是不固定的,空闲区域的大小也是不固定的,数据页目录的大小也是不固定的,然后文件尾部占据8个字节。

math?formula=%5Ccolor%7Bgreen%7D%7B%E6%8E%A5%E7%9D%80%E6%88%91%E4%BB%AC%E6%9D%A5%E7%9C%8B%E4%B8%80%E4%B8%8B%E6%95%B0%E6%8D%AE%E6%8F%92%E5%85%A5%E6%95%B0%E6%8D%AE%E9%A1%B5%E7%9A%84%E8%BF%87%E7%A8%8B%7D,刚开始一个数据页可能是空的,没有一行数据,此时这个数据页实际上是没有数据行那个区域的。假设我们现在要插入一行数据,此时数据库里可是一行数据都没有的,那么此时是不是应该先从磁盘上加载一个空的数据页到缓存页里去?加载的过程我们通过一张图来看一下:

96a1b4ccded1

datapage3.jpg

接着我们是不是应该在buffer pool中的一个空的缓存页里插入一条数据?记住,缓存页跟数据页是一一对应的,它在磁盘上的时候就是数据页,数据页加载到缓存里了,我们就叫它缓存页。所以此时在缓存页里插入一条数据,实际上就是在数据行那个区域里插入一行数据,然后空闲区域的空间会减少一些,此时当缓存页里插入了一行数据之后,缓存页此时看起来如下图所示:

96a1b4ccded1

datapage4.png

接着你就可以不停的插入数据到这个缓存页里,直到它的空闲区域都耗尽了,就是这个页满了,此时数据行区域内可能有很多行数据。大家都知道,在更新缓存页的同时,其实它在lru链表里的位置会不停的变动,而且肯定会在flush链表里,所以最终它一定会通过后台IO线程根据lru链表和flush链表,把这个脏的缓存页刷到磁盘上去。如下图所示:

96a1b4ccded1

datapage5.png

表空间、数据区

math?formula=%5Ccolor%7Bgreen%7D%7B%E4%BB%80%E4%B9%88%E6%98%AF%E8%A1%A8%E7%A9%BA%E9%97%B4%EF%BC%9F%7D简单来说,就是平时我们创建的那些表,其实都有一个表空间的概念,在磁盘上都会对应着“表名.ibd”这样的一个磁盘数据文件。所以在物理层面,表空间就是对应一些磁盘上的数据文件。有的表空间,比如系统表空间可能对应的是多个磁盘文件,我们自己创建的表对应的表空间可能就是对应了一个“表名.ibd”数据文件。

在表空间的磁盘文件里会有很多的数据页,但是如果一个表空间包含了太多数据页的话就不便于管理,所以在表空间里又引入了一个

math?formula=%5Ccolor%7Bgreen%7D%7B%E6%95%B0%E6%8D%AE%E5%8C%BA%7D的概念,英文就是extent,一个数据区对应着连续的64个数据页,每个数据页是16kb,所以一个数据区是1mb,然后256个数据区被划分为一组。

对于表空间而言,它的第一组数据区的第一个数据区的前3个数据页都是固定的,里面存放了一些描述性的数据。比如fsp_hdr这个数据页,它里面就存放了表空间和这一组数据区的一些属性。ibuf_bitmap数据页,里面存放的是这一组数据页的所有insert buffer的一些信息。inode数据页,这里也存放了一些特殊信息。

我们现在先不去具体了解它们是干什么的,只要知道第一组数据区的第一个数据区的前3个数据页,都是存放一些特殊信息的。然后这个表空间里的其它各组数据区,每一组数据区的第一个数据区的头两个数据页都是存放特殊信息的,比如xdes数据页就是用来存放这一组数据区的一些相关属性的,其实就是很多描述这组数据区的东西。下面我们通过一张图来看一下表空间的存储结构。

96a1b4ccded1

datapage6.jpg

生产经验

1、linux操作系统的存储系统软件层原理分析以及IO调度优化原理

简单来说,linux的存储系统分为VFS层、文件系统层,Page Cache缓存层,通用Block层、IO调度层、Block设备驱动层、Block设备层,如下图:

96a1b4ccded1

block1.jpg

当MySQL发起一次数据页的随机读写,或者是一次redo log日志文件的顺序读写的时候,实际上会把磁盘IO请求交给linux操作系统的VFS层。这一层的作用,就是根据你是对哪个目录中的文件执行的磁盘IO操作,把IO请求交给具体的文件系统。

举个例子,在linux中,有的目录比如/xx1/xx2里的文件是由NFS文件系统管理的,有的目录比如/xx3/xx4里的文件其实是由Ext3文件系统管理的,那么这个时候VFS层需要根据你是对哪个目录下的文件发起的读写IO请求,把请求转交给对应的文件系统。

接着,文件系统会先在Page Cache这个基于内存的缓存里找你要的数据在不在里面,如果有就基于内存缓存来执行读写,如果没有就继续往下一层走,此时这个请求会交给通用Block层,在这一层会把你对文件的IO请求转换为Block IO请求。

接着IO请求转换为Block IO请求之后,会把这个Block IO请求交给IO调度层,在这一层里默认是用CFQ公平调度算法的,也就是说,假设此时数据库发起了多个SQL语句同时在执行IO操作。

有的SQL语句可能非常简单,比如“update xxx set xx1=xx2 where id =1”,它可能就只要更新磁盘上的一个block里的数据就可以了,但是有的SQL语句,比如说“select * from xx where xx1 like ‘%xx%’”可能需要IO读取磁盘上的大量数据。那么此时如果基于公平调度算法,就会导致它先执行第二个SQL语句的读取大量数据的IO操作,耗时很久,然后第一个仅仅更新少量数据的SQL语句的IO操作,就一直在等待它,得不到执行的机会。

所以一般建议MySQL的生产环境,需要调整为deadline IO调度算法,它的核心思想就是,任何一个IO操作都不能一直在不停的等待,在指定时间范围内,都必须让它去执行。所以基于deadline算法,上面第一个SQL语句的更新少量数据的IO操作可能在等待一会之后就得到执行的机会,这也是一个生产环境的IO调度优化经验。

最后IO完成调度之后,就会决定哪个IO请求先执行,哪个IO请求后执行,此时可以执行的IO请求就会交给Block设备驱动层,最后经过驱动把IO请求发送给真正的存储硬件,也就是Block设备层。硬件设备完成IO读写操作,最后就把响应经过上面的层级反向依次返回,最终MySQL可以得到本次IO读写操作的结果。

math?formula=%5Ccolor%7Bgreen%7D%7B%E6%9C%AC%E6%96%87%E7%BB%93%E6%9D%9F%7D

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值