MySQL阅读笔记——13.InnoDB缓存池
表空间
# 在配置文件中配置Buffer Pool大小,单位是字节,不配置默认128M,最小值是5M [server] innodb_buffer_pool_size = 268435456
Buffer Pool
本质是向操作系统申请一块连续的内存空间,用来缓存磁盘页面、锁信息、自适应哈希索引 ,Buffer Pool
默认由缓存页和控制块组成,每一个缓存页都对应一个控制块,缓存页大小和磁盘上一样都是16KB,控制块在Buffer Pool
结构的前部,缓存也在后部。通过哈希处理确定页面是否被缓存(对 表空间+页号 作为key,缓存页作为value存储为哈希表)
控制块中包含了对应缓存页的控制信息,如:页所属表空间的边号、页号、缓存页在
Buffer Pool
中的地址、链表节点信息、锁信息、LSN信息,控制块的大小约占缓存页的5%在MySQL5.7中每个控制块是808字节,设置的innodb_buffer_pool_size
并不包含控制块占用的内存空间,因此InnoDB申请Buffer Pool
会比innodb_buffer_pool_size
大5%
InnoDB使用了很多双向链表管理buffer pool
的控制块结构(在MySQL5.7每个链表的基节点只占用40字节大小且并不计算在innodb_buffer_pool_size
中):
-
free双向链表:存放所有空闲缓存页,从磁盘加载页时会从中取一个空闲页面,并把控制信息填上,然后从
free链表
删除该缓存页 -
flush双向链表:被修改了数据的缓存页面叫 脏页,所有的 脏页 构成的链表
-
LRU双向链表:按照某个比例将LRU链表分成两部分,前半部分是
young区域
代表使用频率高的缓存页,后半部分是old区域
代表使用频率不高的区域,第一次访问页面数据会加入到old区域
头部(每次读取一条记录都算一次访问页面),随着访问次数增加会将热点数据转移到young区域
,头部数据都是新访问的数据,尾部数据都是很久之前访问数据,当Buffer Pool
缓存页空间用完时,会从尾部淘汰页面 -
还有一些其他链表,如:unzip LRU双向链表管理解压页,zip clean链表管理没有被解压的压缩页,zip free数组每一个元素都是一个链表,他们构成 伙伴系统 为压缩页提供内存空间
InnoDB提供 预读 功能,分为两种:
线性预读: 通过
innodb_read_ahead_threshold
系统变量控制(默认56),顺序访问某个区的页面超过这个值,则会触发 异步 读取下一个 区 中全部的页面到Buffer Pool
随机预读:
通过
innodb_random_read_ahead
兄变量控制(默认OFF
)如果Buffer Pool
的young区域中的头部1/4已经缓存了某个区的13个 连续页面,不论这些页面是不是顺序读取,则会出发一次 异步 读取本区所有的其它页面的请求
针对LRU双向链表优化:
首次加载页面,该缓存页控制块放到 LRU双向链表的old区头部
通过
innodb_old_blocks_time
系统变量控制(默认1000毫秒),第一次访问页面和最后一次访问页面的时间间隔小于设置,则不会加入到young区域,如果设置为0,则第一次访问就会把该页面放到young头部在
young区域
,只有被访问的缓存位于1/4后边,才会被移动到 LRU双向链表 头部,降低young区域
调整频率,提升性能
Buffer Pool
中没有可用缓存页时,会尝试直接释放 LRU双向链表 尾部没有修改的页面,如果没有则会将尾部的 脏页 同步到磁盘MySQL5.7后,通过
chunk
为单位申请Buffer Pool
大小,一个Buffer Pool
实例包含若干个相同结构的chunk
启动MySQL服务器时可以通过系统变量innodb_buffer_pool_chunk_size
指定(默认128M),只能在启动时指定,运行过程中不可修改*
nnodb_buffer_pool_size
必须是innodb_buffer_pool_chunk_size × innodb_buffer_pool_instances
的倍数,如果在服务器启动时,innodb_buffer_pool_chunk_size × innodb_buffer_pool_instances
的值已经大于innodb_buffer_pool_size
的值,那么innodb_buffer_pool_chunk_size
的值会被服务器自动设置为innodb_buffer_pool_size/innodb_buffer_pool_instances
的值。刷新脏页到磁盘:
从 LRU双向链表 的
old区域
刷新一部分页面到磁盘从 flush链表 刷新一部分数据到磁盘