1.配置Buffer Pool大小

Buffer Pool默认是128MB,在生产环境下我们可以根据实际情况对其进行修改。
比如,数据库如果部署在16核32G的机器上,我们可以给Buffer Pool分配2G的内存。
innodb_buffer_pool_size = 2147483648

2.数据页:MySQL中抽象出来的数据单位

03_Buffer Pool - 图1
数据页也就是B+树叶子节点,默认大小16KB。
当更新一行数据时,数据库会找到这行数据所在的数据页,然后从磁盘文件里把这行数据所在的数据页加载到Buffer Pool中。

3.Buffer Pool中的缓存页对应的描述信息

每个缓存页,都会有一个描述信息,这个描述信息包含以下内容:这个数据页所属的表空间、数据页的编号、缓存也在Buffer Pool中的地址等。
03_Buffer Pool - 图2
Buffer Pool中的描述数据相当于缓存页的5%左右,也就是每个描述数据大概是800字节大小。假设Buffer Pool大小是128MB,实际上Buffer Pool真正的大小会超出一些,大概130MB。

4.数据库启动时,如何初始化Buffer Pool

数据库启动时,会按照设置的Buffer Pool大小,稍微加大一点,去操作系统中申请一块内存区域,作为Buffer Pool的内存区域。当内存区域申请完毕之后,数据库会按照默认的缓存页的16KB的大小以及对应的800字节左右的描述数据的大小,在Buffer Pool中划分出来一个一个的缓存页和对应的描述数据。这个时候缓存页都是空的,当进行增删改查的操作的时候,才会把数据从磁盘读出来,放入缓存页中。

5.free链表:记录空闲缓存页

Buffer Pool中设计了一个free链表,它是一个双向链表数据结构。这个free链表中,每一个节点就是一个空闲的缓存页的描述数据块的地址,也就是说,只要一个缓存页是空闲的,那他的描述数据块就会放入这个free链表中。
free链表中有一个基础节点,他会引用链表的头节点和尾节点,存储了free链表的头节点的地址,尾节点的地址,还有free链表里当前有多少个节点 。
03_Buffer Pool - 图3

6.缓存哈希表:记录已缓存的数据页

在执行增删改查的时候,会先看看这个数据页有没有被缓存,如果没有被缓存,会从free链表中找一个空闲的缓存页,从磁盘上读取数据页写入缓存页,写入描述数据,从free链表中移除这个描述数据块。
数据库有一个哈希表数据结构,它会用表空间号+数据页号,作为一个key去哈希表查一下,如果没有就读取数据页,如果有,就说明数据页已经缓存了。
每读取到一个数据页到缓存之后,都会在这个哈希表写入一个key-value键值对。
03_Buffer Pool - 图4

7.flush链表:记录被修改过的缓存页

Buffer Pool中更新过的数据都是要被刷回磁盘中,但不可能所有的缓存页都刷回磁盘,因为Buffer Pool中的缓存页不一定都是被修改过的。
数据库中引入了一个跟free链表类似的flush链表,凡是修改过的缓存页,都会被放入flush链表中,然后被flush到磁盘上。
03_Buffer Pool - 图5

8.设置多个Buffer Pool

通过修改MySQL服务端的配置,可设置多个Buffer Pool:

  1. [server]
  2. innodb_buffer_pool_size = 8589934592
  3. innodb_buffer_pool_instances = 4

给buffer pool设置8GB的总内存,然后设置了4个buffer pool,每个buffer pool的大小就是2GB。
多个线程同时操作可以在不同的buffer pool中加锁,可以极大提高mysql并发能力。

9.通过chunk支持数据库运行期间Buffer Pool动态调整

MySQL设计了一个chunk机制,buffer pool是由很多chunk组成的,它的大小由innodb_buffer_pool_chunk_size参数控制,默认是128MB。如果buffer pool是2GB,每个chunk是128MB,那么buffer pool就是16个chunk组成的。
每个buffer pool里的每个chunk里就是一系列的描述数据和缓存页。每个buffer pool里的多个chunk共享一套free、flush、lru这些链表。
03_Buffer Pool - 图6
如果此时buffer pool大小是8GB,要扩充到16GB,只需要申请一系列的128MB大小的chunk就可以了。

10.查看Buffer Pool参数

  1. -- innodb buffer pool缓存池中包含数据的页的数目,包括脏页。单位是page
  2. show global status like 'Innodb_buffer_pool_pages_data';
  3. -- innodb buffer pool的页总数目。单位是page
  4. show global status like 'Innodb_buffer_pool_pages_total';
  5. -- 查看@@innodb_buffer_pool_size大小,单位字节(字节转MB
  6. SELECT @@innodb_buffer_pool_size/1024/1024;
  7. -- 在线调整InnoDB缓冲池大小(单位字节),如果不设置,默认为128M
  8. set global innodb_buffer_pool_size = 4227858432;