Buffer Pool

简介:Innodb维护了一个缓存区域叫做Buffer Pool,用来缓存数据和索引在内存中。Buffer Pool可以用来加速数据的读写,如果Buffer Pool越大,那么Mysql就越像一个内存数据库,所以了解Buffer Pool的配置可以提高Buffer Pool的性能。

buffer pool的配置

innodb_buffer_pool_size:缓存区域的大小。
innodb_buffer_pool_chunk_size:当增加或减少innodb_buffer_pool_size时,操作以块(chunk)形式执行。块大小由innodb_buffer_pool_chunk_size配置选项定义,默认值128M。
innodb_buffer_pool_instances:当buffer pool比较大的时候(超过1G),innodb会把buffer pool划分成几个instances,这样可以提高读写操作的并发,减少竞争。读写page都使用hash函数分配给一个instances。
当增加或者减少buffer pool大小的时候,实际上是操作的chunk。buffer pool的大小必须是innodb_buffer_pool_chunk_sizeinnodb_buffer_pool_instances,如果配置的innodb_buffer_pool_size不是innodb_buffer_pool_chunk_sizeinnodb_buffer_pool_instances的倍数,buffer pool的大小会自动调整为innodb_buffer_pool_chunk_size*innodb_buffer_pool_instances的倍数,自动调整的值不少于指定的值。
如果指定的buffer大小是9G,instances的个数是16,chunk默认的大小是128M,那么buffer会自动调整为10G。具体的配置可以参考mysql官网的介绍mysql reference

LRU算法

为了管理这些数据,innodb使用了一些链表。
lru链表:用来存储内存中的缓存数据。
free链表:用来存放所有的空闲页,每次需要数据页存储数据时,就首先检测free中有没有空闲的页来分配。
flush链表:在内存中被修改但还没有刷新到磁盘的数据页列表,就是所谓的脏页列表,内存中的数据跟对应的磁盘上的数据不一致,属于该列表的页面同样存在于lru列表中,但反之未必。

防止缓存污染

思考一个问题,如果msyql做一次全表扫描,那么全表扫面的数据就会放到buffer pool中,而且全表扫描的数据大部分都是用不到的,那么之前的热点数据也就被冲掉了。所以innodb有一些策略来防止缓存污染。
在Buffer Pool中,存储数据的最小单位是页,默认是16K,使用LRU算法的变体来进行页数据的淘汰和置换。Buffer Pool把LRU链表分为两个部分,一个部分叫做头部链表用来存储热点数据,一个部分叫做尾部链表,用来存储即将淘汰的数据。头部链表和尾部链表有一个分界点,默认是3/8,就是有3/8的空间用来存储old页面。在innodb中有个参数是innodb_old_blocks_pct,默认是37大概就是3/8,通过配置这个参数可以选择头部链表和尾部链表占用的空间比例,innodb_old_blocks_pct的可配置的范围是从5-95,值越大说明尾部链表占用的空间越大,也就越接近LRU算法。当mysql从磁盘往缓存区存数据的时候,都会先把数据存储在尾部链表,这样一来,即使有全表扫描,那么全表扫描的数据也只能进入尾部链表中,不会影响头部链表的数据。
在innodb中还有一个参数也是用来防止缓存污染的,就是innodb_old_blocks_time。这个参数的默认值是1000ms,意思是,在把数据读入尾部链表的1000ms之内,再次访问相同的数据,这个数据页不会进入到头部链表。这个值越大,那么数据进入头部链表的机会就越少,那么数据被淘汰的概率就越大。

预读操作

预读是mysql提高性能的一个重要的特性。预读是指,在获取一个页面的数据时,在不久的时间里面也会用到存储数据页面的后面的页面(page)或者块(extend)。在mysql中预读有两种。

Linear线性预读

线性预读的单位是extend,一个extend中有64个page。线性预读的一个重要参数是innodb_read_ahead_threshold,是指在连续访问多少个页面之后,把下一个extend读入到buffer pool中,不过预读是一个异步的操作。当然这个参数不能超过64,因为一个extend最多只有64个页面。
例如,innodb_read_ahead_threshold = 56,就是指在连续访问了一个extend的56个页面之后把下一个extend读入到buffer pool中。在添加此参数之前,InnoDB仅计算当它在当前范围的最后一页中读取时是否为整个下一个范围发出异步预取请求。

Random随机预读

随机预读方式则是表示当同一个extent中的一些page在buffer pool中发现时,Innodb会将该extent中的剩余page一并读到buffer pool中。由于随机预读方式给innodb code带来了一些不必要的复杂性,同时在性能也存在不稳定性,在5.5中已经将这种预读方式废弃,默认是OFF。若要启用此功能,即将配置变量设置innodb_random_read_ahead为ON。

数据页访问流程

  1. 当访问的页面在缓存池在命中的话,直接返回该页。为了避免扫描LRU,innodb为每个instances维护了一个page hash,通过space id和page no可以直接找到对应的page。一般情况下,当我饿你需要读入一个Page时,首先根据space id和page no找到对应的instances,然后再查询page hash,如果page hash中没有,则需要从磁盘中读取。
  2. 如果没有命中,则需要把页面从磁盘加载到缓存池中,因此需要在缓存池中找到一个空闲的内存块来缓存这个页面。
  3. 如果空闲内存被使用完,也就是free链表上没有内存块了。则需要在生产一个空闲的内存块。
  4. 首先去LRU列表中找可以替换的内存页面,查找的方向是从列表的尾部开始找,如果找到可以替换的页面,将其从LRU列表中摘除,加入空闲列表,然后再去空闲列表中找空闲的内存块。第一查找最多值扫描100个页面,循环进行到第二次时,会扫描整个LRU列表。
  5. 如果在LRU列表中没有找到可以替换的页,则进行单页刷新,将脏页刷新到磁盘之后,然后将释放的内存块加入到空闲列表。然后再去空闲列表中取。为什么只做单页刷新呢?因为这个函数的目的是获取空闲内存页,进行脏页刷新是不得已而为之,所以只会进行一个页面的刷新,目的是为了尽快的获取空闲内存块。

通过数据页访问机制,可以知道其中当无空闲页时产生空闲页就成为一个必须要做的事情了。如果需要刷新脏页来产生空闲页面或者需要扫描整个LRU列表来产生空闲页面的时候,查找空闲内存块的时间就会延长,这个是一个bad case,是我们希望尽量避免的。因此,innodb buffer pool中存在大量可以替换的页面,或者free列表中一直存在着空闲内存块,对快速获取到空闲内存块起决定性的作用。

缓存池刷新策略

InnoDB会在后台执行某些任务,包括从缓冲池刷新脏页(那些已更改但尚未写入数据库文件的页)。

当启用innodb_max_dirty_pages_pct_lwm(默认值0)参数时,表示启用了脏页面预刷新行为,以控制脏页面占比。也是为了防止脏页占有率超过innodb_max_dirty_pages_pct(默认值75%)的设定值。默认禁用“预刷新”行为。如果当脏页的占有率达到了innodb_max_dirty_pages_pct的设定值的时候,InnoDB就会强制刷新buffer pool pages。另外当free列表小于innodb_lru_scan_depth值时也会触发刷新机制,innodb_lru_scan_depth控制LRU列表中可用页的数量,该值默认为1024。

后台刷新的动作由后台刷新协调线程触发,该线程的所有工作内容均由buf_flush_page_cleaner_coordinator函数完成,我们后面简称它为协调函数。接下来,来看后台刷新协调函数的主体流程。

  1. 调用page_cleaner_flush_pages_recommendation建议函数,对每个缓冲池实例生成脏页刷新数量的建议。在执行刷新之前,会用建议函数生成每个buffer pool需要刷新多少个脏页的建议。

  2. 生成刷新建议之后,通过设置事件的方式,向刷新线程(Page Cleaner线程)发出刷新请求。后台刷新线程在收到请求刷新的事件后,会执行pc_flush_slot函数对某个缓存池进行刷新,刷新的过程首先是对lru列表进行刷新,执行的函数为buf_flush_LRU_list,完成LRU列表的刷新之后,就会根据建议函数生成的建议对脏页列表进行刷新,执行的函数为buf_flush_do_batch。

  3. 后台刷新的协调线程会作为刷新调度总负责人的角色,它会确保每个buffer pool都已经开始执行刷新。如果哪个buffer pool的刷新请求还没有被处理,则由刷新协调线程亲自刷新,且直到所有的buffer pool instance都已开始/进行了刷新,才退出这个while循环。

  4. 当所有的buffer pool instance的刷新请求都已经开始处理之后,协调函数(或协调线程)就等待所有buffer pool instance的刷新的完成,等待函数为pc_wait_finished。如果这次刷新的总耗时超过4000ms,下次循环之前,会在数据库的错误日志记录相关的超时信息。它期望每秒钟对buffer pool进行一次刷新调度。如果相邻两次刷新调度的间隔超过4000ms ,也就是4秒钟,MySQL的错误日志中会记录相关信息,意思就是“本来预计1000ms的循环花费了超过4000ms的时间。

前面我们反复讲到,每个buffer pool需要刷新多少页面是由建议函数生成的,它在做刷新建议的时候,具体考虑了哪些因素?现在我们来详细解析。

在讲这段内容之前,我们先来了解两个参数:innodb_io_capacity与innodb_io_capacity_max,这两个参数大部分朋友都不陌生,设置这个参数的目的,是告诉MySQL数据库,它所在服务器的磁盘的随机IO能力。MySQL数据库目前还没有去自己评估服务器磁盘IO能力的功能,所以磁盘io能力大小由这个参数提供,以便让数据库知道磁盘的实际IO能力。这个参数将直接影响建议刷新的页面的数量。

建议函数它会计算当前的脏页刷新平均速度(也就是一秒钟刷新了多少脏页)以及重做日志的生成平均速度。但这个函数并不是每次被调用时,都计算一次平均速度。它是多久计算一次的呢?这个是由数据库参数innodb_flushing_avg_loops来决定的,默认是30,当这个函数被调用了30次之后或者经过30秒之后,重新计算一次平均值。我们暂且简单理解为30秒钟。计算规则是当前的平均速度加上最近30秒钟期间的平均速度再除以2得出新的平均速度。两个平均值相加再平均,得出新的平均值。这样的平均值能明显的体现出最近30秒的速度的变化。

<参考>
http://www.ywnds.com/?p=9886
https://dev.mysql.com/doc/refman/5.7/en/innodb-buffer-pool.html#innodb-buffer-pool-lru

博主博客地址:www.javajs.cn

Mysql Buffer Pool相关推荐

  1. MySQL buffer pool里的三种链表和三种page

    mysql buffer pool里的三种链表和三种page buffer pool是通过三种list来管理的 1) free list 2) lru list 3) flush list buffe ...

  2. MySQL buffer pool中的三种链

    三种page.三种list.LRU控制调优 一.innodb buffer pool中的三种页 1.free page:从未用过的页 2.clean page:干净的页,数据页的数据和磁盘一致 3.d ...

  3. 关于MySQL buffer pool的预读机制

    预读机制 两种预读算法 1.线性预读 2.随机预读 对预读的监控 一.预读机制 InnoDB在I/O的优化上有个比较重要的特性为预读,预读请求是一个i/o请求,它会异步地在缓冲池中预先回迁多个页面,预 ...

  4. MySQL 引擎特性 · InnoDB Buffer Pool

    前言 用户对数据库的最基本要求就是能高效的读取和存储数据,但是读写数据都涉及到与低速的设备交互,为了弥补两者之间的速度差异,所有数据库都有缓存池,用来管理相应的数据页,提高数据库的效率,当然也因为引入 ...

  5. [转]MySQL innodb buffer pool

    最近在对公司的 MySQL 服务器做性能优化, 一直对 innodb 的内存使用方式不是很清楚, 乘这机会做点总结. 在配置 MySQL 的时候, 一般都会需要设置 innodb_buffer_poo ...

  6. mysql 哈希缓存_MySQL Buffer Pool

    1.简介 buffer pool 就是一个缓存,将磁盘中的数据缓存到内存中,对数据的操作改为通过内存进行操作,然后刷盘的操作,提升性能. innodb_buffer_pool_size 控制缓存池的大 ...

  7. MySQL · 性能优化· InnoDB buffer pool flush策略漫谈

    MySQL · 性能优化· InnoDB buffer pool flush策略漫谈 背景 我们知道InnoDB使用buffer pool来缓存从磁盘读取到内存的数据页.buffer pool通常由数 ...

  8. 缓冲多少数据_聊点深的:解析MySQL,看看InnoDB 缓冲池(buffer pool) 工作原理

    缓冲池的用处 对于使用 InnoDB 作为存储引擎的表来说,不管是用于存储用户数据的索引,还是各种系统数据,都是以页的形式存放在表空间中的,而所谓的表空间只是 InnoDB 对文件系统上一个或几个实际 ...

  9. mysql buffer pool_MySQL的查询缓存和Buffer Pool

    一.Caches - 查询缓存 下图是MySQL官网给出的:MySQL架构体系图. 人们常说的查询缓存就是下图中的Cache部分. 如果将MySQL分成 Server层和存储引擎层两大部分,那么Cac ...

  10. 分页缓冲池占用很高怎么解决_聊点深的:解析MySQL,看看InnoDB 缓冲池(buffer pool) 工作原理...

    缓冲池的用处 对于使用 InnoDB 作为存储引擎的表来说,不管是用于存储用户数据的索引,还是各种系统数据,都是以页的形式存放在表空间中的,而所谓的表空间只是 InnoDB 对文件系统上一个或几个实际 ...

最新文章

  1. 自动驾驶年度成绩单公布:中国公司亮眼,报告标准惹争议
  2. node中的流的介绍(Stream)
  3. Kotlin的基本数值类型问题:是对象?还是基本数据类型?
  4. python中字符串注意事项
  5. 各种网络模拟器的下载链接
  6. linux-vim设置环境
  7. 为什么说只有深度思考才能让你持续赚到钱?
  8. 绘制箱线图的标签python_利用Python - Matplotlib 绘制箱线图
  9. Django积木块八——三级联动
  10. fread函数在C语言中的用法,c语言fread函数的用法
  11. 给大家推荐一个前端非常好用的量图软件(只能量psd的哦)像素大厨 PxCook 像素大厨使用方法
  12. 数据结构实验C语言实现版
  13. 员工绩效考核指标设计主要原则(zt)
  14. 什么是幂等性?四种接口幂等性方案详解
  15. IT统一运维软件发展趋势浅析
  16. 【校招VIP】互联网校招项目实习对项目的要求不重要?大错特错!你忽略掉的项目考察重点都在这里!
  17. 微型四轴DIY机架,轻巧稳固耐摔,通用720空心杯电机,9厘米轴距
  18. 中小学人工智能、机器人、计算机编程等全国性竞赛和课程资料分享(2019年度)
  19. loopback一些相关操作【loopback3.x升级为loopback4】
  20. 被尘封的故事技能点bug_梦幻西游:官方都不承认存在的BUG,可以同时完成两个奇谭任务...

热门文章

  1. C1 驾驶证考试科目二考试心得
  2. linux格式化sd卡,并进行挂载
  3. python输出偶数_如何用Python 判断奇偶数
  4. 工控硬件芯片级电路板维修方法
  5. [人脸关键点检测] Wing loss 论文解读
  6. 网吧服务器系统机房图片,很多网吧看不到主机的秘密
  7. day04 1113 红与黑(flood fill算法,即DFS,BFS)
  8. windows 无法停止ics_多种方法解决Win10系统ICS服务启动后停止问题
  9. QR扫码综合示例教程(六)Qt6.2.1(widget)取出视频帧 取景器帧
  10. Ubuntu 使用上的一些小tip