buffer pool 中的数据结构

1 buffer pool 初始化
buffer pool存在于内存中,是innoDB的核心组件,增删改操作都是作用在buffer pool上。
buffer pool的大小可以通过 innodb_buffer_pool_size(核心参数) 配置。
buffer pool缓存的是一个个数据页,数据页里存的是一行行数据。
每个缓存页对应一个元数据块,存储缓存页的地址,数据页的表空间、页号信息等。

数据库启动时,根据 innodb_buffer_pool_size,加上元数据的内存,向 os 申请一块内存。
申请了内存后,按照数据页大小和元数据大小,分出一个个缓存页及相应的元数据。
截屏2021-08-17 下午1.35.27.png
2 free链表和flush链表
这两个链表是由元数据块的节点构成双向链表,每个节点包含pre和next指针。

free链表用于组织空闲缓存页;flush链表用于组织脏页(被修改过的缓存页)。
基础节点存储链表的头尾节点信息和长度,元数据块位于buffer pool中。
元数据块存储缓存页所存的数据页的表空间,页号,缓存页的地址等。

截屏2021-08-17 下午5.57.50.png
3 如何判断数据页是否在缓存中
写sql只关注表+行,mysql内部对应表空间+数据页。
有一个哈希表维护了表空间+数据页号到缓存页地址的映射,如果存在,则说明被缓存。

4 缓存页的LRU淘汰机制
维护一个LRU链表,最近被访问的被放到链表头部。
截屏2021-08-17 下午8.12.57.png
LRU 淘汰存在的问题
mysql 预读机制会加载一些并不需要的数据页,这些数据页放到LRU链表头部。
这样会导致尾部本来被频繁访问的数据页被刷出缓存。

innodb 预读机制的触发时机
顺序访问了一个区的若干数据页,innodb_read_ahead_threshold
或者缓存了一个区的连续数据页,innodb_random_read_ahead

此外,全表扫描也会导致链表尾部频繁访问的数据页可能被淘汰。
截屏2021-08-17 下午8.15.44.png
5 表、行&表空间、数据页
前者是逻辑上的概念;后者是物理上的概念。
正如redo、undo是逻辑上的概念;binlog是物理概念

LRU 链表优化

为了解决预读带来的问题,引入类似于two list的策略 midpoint insertion strategy。
innodb_old_blocks_pct 代表old list的比例,默认值是37,代表37%是冷数据。
new list都是代表最近被访问的数据,也即热点数据。
**

截屏2021-08-18 上午8.36.46.png
innodb_old_blocks_time默认为1000 ms,经过1s,才从old list迁移到new list。
如果time设置太长,或者全表扫描,或者pct设置太小,容易导致old list缓存页被刷出。

通过冷热数据分离,可以解决预读机制和全表扫描带来的问题。
因为预加载和全表扫描的数据页一般1s内被访问,因此不会进入new list。

淘汰缓存页只需要把old list尾部的缓存页刷到磁盘即可。

LRU 改造:针对 new list 中的热点数据,可以采取前3/4被访问的话,不修改数据;
后1/4缓存页被访问,就将其移动到链表头部。

缓存预加载

对于业务数据,基于冷热分离的思想,可以启动一个定时 job,把数据加载到缓存里。

buffer pool 运行机制

1 加载缓存页
free 链表移除该缓存页,lru链表可能将冷数据页移动到链表头部

2 查询缓存页
将缓存页放到链表头部

3 修改缓存页
flush 链表记录脏页,lru链表可能将冷数据页移动到链表头部

4 定时刷缓存
光把lru链表中的冷数据刷入磁盘,是不够的。
后台线程在mysql不忙时,会把flush链表中的数据都刷入磁盘。
同时,这些缓存页也会从flush和lru链表移除。

5 无空闲页
如果 free 链表无空闲页,flush 链表有很多脏页,就从lru链表尾部刷缓存页到磁盘,flush链表删除缓存页,free链表增加缓存页。

buffer pool 与并发

mysql可能同时接收到多个请求,多个线程同时操作 buffer pool里的缓存页和链表。
比如加载缓存页,涉及到IO,会导致其他线程等待,实际可以配置多个buffer pool。
截屏2021-08-18 下午11.41.48.png

buffer pool 的 chunk 机制

每个buffer pool由若干chunk组成,共用free链表,flush链表,lru链表。
支持运行时动态调整buffer pool的大小。
截屏2021-08-19 上午12.10.24.png