背景介绍
在mysql中数据都是存储在磁盘上的,但是磁盘的访问速度非常慢,所以InnoDB存储引擎在处理客户端的请求时,会将数据以页为单位加载到内存数据结构当中,这个内存数据结构就是BufferPool。该区域的大小由innodb_buffer_pool_size控制,默认128M。
BufferPool也可以是多个,个数由innodb_buffer_pool_instances控制,但是如果innodb_buffer_pool_size小于1G时设置多个实例是无效的。
每个BufferPool由多个chunk组成,大小由innodb__buffer_pool_chunk_size控制(默认128M)。innodb_buffer_pool_size必须是innodb_buffer_pool_chunk_size * innodb_buffer_pool_instances的整数倍,如果设置的不是整数倍,innodb会自动将其修改为最小的整数倍
mysql中的BufferPool就是程序启动时向操作系统申请的一段连续内存,由控制块和数据页(与磁盘存储的数据页大小一致)组成。其中还有Free链表、Flush链表和LRU链表
Free链表
Free链表记录了哪些缓存页是可用的,当系统刚刚完成初始化BufferPool时,所有的缓存页都是可用的
当一页数据被加载到内存中时,会从free链表中取一个空闲的缓存页,并且将数据页所在的表空间、页号之类的信息填入其中,然后把缓存页对应的节点从free链表中删除
对于已使用的数据页,通过一个hash表存储了表空间号+页号作为key,缓冲页地址作为value的hash表,从而避确定哪些数据页已在缓存中
Flush链表
当我们在内存中对数据进行修改时,此时内存中的数据与磁盘上的数据不一致,被称为脏页,Flush链表就是记录脏页信息的
LRU链表
LRU链表用于记录数据页的使用频次,以便mysql可以按照最近最少使用的页去淘汰缓存数据
LRU链表将数据分为young区域(热数据)和old区域(冷数据),比重由innodb_old_blocks_pct参数控制(即old区域的比重)。
当数据第一次被加载到内存中时会被加入到old区域的头节点,当第二次访问时间间隔超过innodb_old_blocks_time(默认1s)时,会将数据放到young区域的头部。
对于在young区域的数据来说,只有被访问的数据页在young区域的后1/4,才会被添加到young区域的头部
