MySQL阅读笔记——13.InnoDB缓存池

  表空间 是文件系统上一个或者几个文件抽象,每个文件划分出多个页,当访问数据时,即使只有一条也会把整个数据加载到内存,访问之后 缓存 一段时间,当再次请求时就可以省去I/O开销

# 在配置文件中配置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提供 预读 功能,分为两种:

  1. 线性预读: 通过innodb_read_ahead_threshold系统变量控制(默认56),顺序访问某个区的页面超过这个值,则会触发 异步 读取下一个 中全部的页面到Buffer Pool

  2. 随机预读:

通过innodb_random_read_ahead兄变量控制(默认OFF)如果Buffer Pool的young区域中的头部1/4已经缓存了某个区的13个 连续页面,不论这些页面是不是顺序读取,则会出发一次 异步 读取本区所有的其它页面的请求

针对LRU双向链表优化:

  1. 首次加载页面,该缓存页控制块放到 LRU双向链表的old区头部

  2. 通过innodb_old_blocks_time系统变量控制(默认1000毫秒),第一次访问页面和最后一次访问页面的时间间隔小于设置,则不会加入到young区域,如果设置为0,则第一次访问就会把该页面放到young头部

  3. young区域,只有被访问的缓存位于1/4后边,才会被移动到 LRU双向链表 头部,降低 young区域调整频率,提升性能

  4. Buffer Pool中没有可用缓存页时,会尝试直接释放 LRU双向链表 尾部没有修改的页面,如果没有则会将尾部的 脏页 同步到磁盘

  5. MySQL5.7后,通过chunk为单位申请Buffer Pool大小,一个Buffer Pool实例包含若干个相同结构的chunk启动MySQL服务器时可以通过系统变量innodb_buffer_pool_chunk_size指定(默认128M),只能在启动时指定,运行过程中不可修改

  6. * 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的值。

刷新脏页到磁盘:

  1. LRU双向链表old区域刷新一部分页面到磁盘

  2. flush链表 刷新一部分数据到磁盘

原文地址:https://www.cnblogs.com/leon618/p/13783342.html