BufferPool在数据库运行期间如何进行动态扩容

322 阅读3分钟

「这是我参与11月更文挑战的第7天,活动详情查看:2021最后一次更文挑战

在一个项目上线的时候,前期不是比较重要的时候,申请的资源不是那么的高配,例如:应用实例配置2C4G,数据库配置4C8G,但是在后面随着业务的发展,该项目需要承接比较重要的业务需求,并发访问量一下就上来了,这个时候就需要申请配置,应用实例在最初发布的都是都是微服务体系架构,只需要在发布平台申请更高的配置按照滚动方式重新发布一下服务即可,但是对于数据库来说,为了保障线上业务提供稳定的运行,是不会允许重启数据库的。针对数据库配置增加会遇到两种情况:

  • 1.本身部署的机器内存无法扩容,需要将数据库服务迁移到另外的服务器上,服务器机器无法扩容,只能往高的机器迁移服务;
    1. 机器内存还可以分配更多的内存给MySQL,只需要修改MySQL参数,将操作系统的内存新分配一块给MySQL服务;

当MySQL在运行的时候,当需要动态的调整Buffer Pool的大小,例如将8G调整为16GB,这个时候需要向操作系统新申请一块16GB的连续内存,然后把所有的Buffer Pool中的所有缓存页,描述数据,各种链表都拷贝到新的16GB内存中,这样操作的话,过程比较耗时,在拷贝期间性能也比较低下。还有种方案就是:重启服务,相比这种方案肯定是百分百之百不能接受的,重启的代价还是比较大的,也会影响现有业务。如果这样话,那Buffer Pool在运行时候就绝对不能够支持动态调整大小了。

MySQL为了解决动态扩容,在BufferPool中增加了chunk机制,将BufferPool拆分成一块一块的,如果需要扩容,就在BufferPool中加入一些chunk来动态管理。

chunk机制把Buffer Pool拆分成多个动态管理

MySQL为了解决Buffer Pool运行期间调整大小,设计了chunk机制,将Buffer Pool分成由很多chunk组成,可以通过:innodb_buffer_pool_chunk_size参数控制的,默认值就是128MB。每个Buffer Pool里包含多个chunk,每个chunk包含一系列的描述数据块和缓存页,每个Buffer Pool里的chunk共用一套free,flush,lru链表。大致结构如下图:

image.png

chunk机制动态调整BufferPool大小达到动态扩容效果

有了chunk机制的话,就可以支持动态调整Buffer Pool大小,需要将Buffer Pool内存加大的时候,只需要申请一系列的128MB大小的chunk就可以,然后把新申请的这些chunk内存分配给Buffer Pool,这样的话即扩大了内存,也不用额外的申请连续空间,然后将数据进行拷贝。有了chunk机制的话,如果需要将内存有8G-->16GB,这个时候就不需要像操作系统申请连续的8G内存,运行一段的机器,操作系统很难给出8G连续的内存,因为机器运行中会不断的产生内存碎片,如果要给出连续的内存,就需要启动内存碎片整理机制,会导致机器性能的抖动。有个chunk机器,MySQL只需要想操作系统申请:64个*128M连续的空间就可以。

当我们在设置Buffer Pool的总大小之后,就要考虑设置多个Buffer Pool以及chunk的大小,有个很关键的公式:buffer pool总大小=(chunk大小 * buffer pool数量)的倍数