需要删除、新增记录或更新一个数据页时,如果数据页在内存中就直接更新,而如果这个数据页还没有在内存中的话,在不影响数据一致性的前提下,InooDB 会将这些更新操作缓存在 change buffer中,这样就不需要从磁盘中读入这个数据页了。
purge:将 change buffer 中的操作应用到原数据页,得到最新结果的过程。
触发purge时机:除了访问这个数据页会触发 purge 外,系统有后台线程会定期 purge。在数据库正常关闭(shutdown)的过程中,也会执行 purge 操作。
需要说明的是,虽然名字叫作 change buffer,实际上它是可以持久化的数据。也就是说,change buffer 在内存中有拷贝,也会被写入到磁盘上。
changeBuffer的好处:
1减少mysql读磁盘,加快执行速度
2数据读入内存是需要占用 buffer pool 的,所以这种方式还能够避免占用内存,提高内存利用率。
changeBuffer的问题:
如果在更新或查询操作的时候需要对changeBuffer进行purge操作,会进行大量的磁盘IO操作,那么你的数据库性能会突然受影响,会突然慢一下。
触发purge操作的几种场景
  第一种是“redo log 写满了,要 flush 脏页”,这种情况是 InnoDB 要尽量避免的。因为出现这种情况的时候,整个系统就不能再接受更新了,所有的更新都必须堵住。如果你从监控上看,这时候更新数会跌为 0。
  第二种是“内存不够用了,要先将脏页写到磁盘”,这种情况其实是常态。InnoDB 用缓冲池(buffer pool)管理内存,缓冲池中的内存页有三种状态: 第一是,还没有使用的;第二是,使用了并且是干净页;第三是,使用了并且是脏页,MySQL 会把内存的脏页都 flush 到磁盘上,这样下次 MySQL 启动的时候,就可以直接从磁盘上读数据,启动速度会很快。
  第三种 是MySQL 认为系统“空闲”的时候,自动purge。此时不会产生性能问题
  第四种 MySQL 正常关闭的情况。这时候,MySQL 会把内存的脏页都 flush 到磁盘上,这样下次 MySQL启动的时候,就可以直接从磁盘上读数据,启动速度会很快。此时不会产生性能问题
所以,刷脏页虽然是常态,但是出现以下这两种情况,都是会明显影响性能的:
1.一个查询要淘汰的脏页个数太多,会导致查询的响应时间明显变长;
2.日志写满,更新全部堵住,写性能跌为 0,这种情况对敏感业务来说,是不能接受的。
所以,InnoDB 需要有控制脏页比例的机制,来尽量避免上面的这两种情况。
InnoDB 刷脏页的控制策略
首先,你要正确地告诉 InnoDB 所在主机的 IO 能力,这样 InnoDB 才能知道需要全力刷脏页的时候,可以刷多快。这就要用到 innodb_io_capacity 这个参数了,它会告诉 InnoDB 你的磁盘能力。这个值我建议你设置成磁盘的 IOPS。磁盘的 IOPS 可以通过 fio 这个工具来测试,下面的语句是我用来测试磁盘随机读写的命令:
fio -filename=$filename -direct=1 -iodepth 1 -thread -rw=randrw -ioengine=psync -bs=16k -size=500M -numjobs=10 -runtime=10 -group_reporting -name=mytest
其实,因为没能正确地设置 innodb_io_capacity 参数,而导致的性能问题也比比皆是。之前,就曾有其他公司的开发负责人找我看一个库的性能问题,说 MySQL 的写入速度很慢,TPS 很低,但是数据库主机的 IO 压力并不大。经过一番排查,发现罪魁祸首就是这个参数的设置出了问题。
他的主机磁盘用的是 SSD,但是 innodb_io_capacity 的值设置的是 300。于是,InnoDB 认为这个系统的能力就这么差,所以刷脏页刷得特别慢,甚至比脏页生成的速度还慢,这样就造成了脏页累积,影响了查询和更新性能。
虽然我们现在已经定义了“全力刷脏页”的行为,但平时总不能一直是全力刷吧?毕竟磁盘能力不能只用来刷脏页,还需要服务用户请求。所以接下来,我们就一起看看 InnoDB 怎么控制引擎按照“全力”的百分比来刷脏页。
根据我前面提到的知识点,试想一下,如果你来设计策略控制刷脏页的速度,会参考哪些因素呢?
这个问题可以这么想,如果刷太慢,会出现什么情况?首先是内存脏页太多,其次是 redo log 写满。所以,InnoDB 的刷盘速度就是要参考这两个因素:一个是脏页比例,一个是 redo log 写盘速度。InnoDB 会根据这两个因素先单独算出两个数字。参数 innodb_max_dirty_pages_pct 是脏页比例上限,默认值是 75%。InnoDB 会根据当前的脏页比例(假设为 M),算出一个范围在 0 到 100 之间的数字,计算这个数字的伪代码类似这样:
F1(M)
{
if M>=innodb_max_dirty_pages_pct then
return 100;
return 100*M/innodb_max_dirty_pages_pct;
}
InnoDB 每次写入的日志都有一个序号,当前写入的序号跟 checkpoint 对应的序号之间的差值,我们假设为 N。InnoDB 会根据这个 N 算出一个范围在 0 到 100 之间的数字,这个计算公式可以记为 F2(N)。F2(N) 算法比较复杂,你只要知道 N 越大,算出来的值越大就好了。
根据上述算得的 F1(M) 和 F2(N) 两个值,取其中较大的值记为 R,之后引擎就可以按照 innodb_io_capacity 定义的能力乘以 R% 来控制刷脏页的速度。 
purge的连坐策略
一旦一个查询请求需要在执行过程中先 flush 掉一个脏页时,这个查询就可能要比平时慢了。而 MySQL 中的一个机制,可能让你的查询会更慢:在准备刷一个脏页的时候,如果这个数据页旁边的数据页刚好是脏页,就会把这个“邻居”也带着一起刷掉;而且这个把“邻居”拖下水的逻辑还可以继续蔓延,也就是对于每个邻居数据页,如果跟它相邻的数据页也还是脏页的话,也会被放到一起刷。
在 InnoDB 中,innodb_flush_neighbors 参数就是用来控制这个行为的,值为 1 的时候会有上述的“连坐”机制,值为 0 时表示不找邻居,自己刷自己的。
找“邻居”这个优化在机械硬盘时代是很有意义的,可以减少很多随机 IO。机械硬盘的随机 IOPS 一般只有几百,相同的逻辑操作减少随机 IO 就意味着系统性能的大幅度提升。
而如果使用的是 SSD 这类 IOPS 比较高的设备的话,我就建议你把 innodb_flush_neighbors 的值设置成 0。因为这时候 IOPS 往往不是瓶颈,而“只刷自己”,就能更快地执行完必要的刷脏页操作,减少 SQL 语句响应时间。
在 MySQL 8.0 中,innodb_flush_neighbors 参数的默认值已经是 0 了。
InnoDB 会在后台刷脏页,而刷脏页的过程是要将内存页写入磁盘。所以,无论是你的查询语句在需要内存的时候可能要求淘汰一个脏页,还是由于刷脏页的逻辑会占用 IO 资源并可能影响到了你的更新语句,都可能是造成你从业务端感知到 MySQL“抖”了一下的原因。
针对purge导致的性能抖动问题,解决方案如下:
1合理地设置 innodb_io_capacity 的值
2平时要多关注脏页比例,不要让它经常接近 75% 
3 设置innodb_flush_neighbors为0 
 
其中,脏页比例是通过 Innodb_buffer_pool_pages_dirty/Innodb_buffer_pool_pages_total 得到的,具体的命令参考下面的代码:
mysql> select VARIABLE_VALUE into @a from global_status where VARIABLE_NAME = 'Innodb_buffer_pool_pages_dirty';
select VARIABLE_VALUE into @b from global_status where VARIABLE_NAME = 'Innodb_buffer_pool_pages_total';
select @a/@b;
---------------------
作者:深山猿
来源:CSDN
原文:https://blog.csdn.net/h2604396739/article/details/85115940

Mysql 了解changeBuffer 与 purge 调优的更多相关文章

  1. MySQL慢查询查找和调优测试

    MySQL慢查询查找和调优测试,接下来详细介绍,需要了解的朋友可以参考下.本文参考自:http://www.jbxue.com/db/4376.html  编辑 my.cnf或者my.ini文件,去除 ...

  2. MySQL 5.6初始配置调优

    原文链接: What to tune in MySQL 5.6 after installation原文日期: 2013年09月17日翻译日期: 2014年06月01日翻译人员: 铁锚 随着 大量默认 ...

  3. Mysql运行状态查询命令及调优详解

    (转载自点击打开链接) MySQL运行状态及调优(一) 一.查看MySQL运行情况SHOW STATUS; 二.查看INNODB数据库引擎运行状态SHOW ENGINE INNODB STATUS; ...

  4. 用MySQL的optimizer_trace进行sql调优

    在我们调优MySQL的SQL时候,通常使用三种工具进行查看sql执行的效率,explain.profile.optimizer_trace.前两个经常被人使用,由于第三个难度较大,大家使用的较少,下面 ...

  5. Mysql千万级数据性能调优配置

    背景: 笔者的源数据一张表大概7000多万条,数据大小36G,索引6G,加起来表空间有40G+,类似的表有4张,总计2亿多条 数据库mysql,引擎为innodb,版本5.7,服务器内存256G,物理 ...

  6. MYSQL企业常用架构与调优经验分享

    一.选择Percona Server.MariaDB还是MYSQL  mysql应用源码:http://www.jinhusns.com/Products/Download/?type=xcj 1.M ...

  7. MYSQL数据库的设计与调优

    优化思路: 1.检查数据表结构,改善不完善设计 2.跑一遍主要业务,收集常用的数据库查询SQL 3.分析查询SQL,适当拆分,添加索引等优化查询 4.优化SQL的同时,优化代码逻辑 5.添加本地缓存和 ...

  8. MYSQL 企业常用架构与调优经验分享

    一.选择Percona Server.MariaDB还是MYSQL  mysql应用源码:http://www.jinhusns.com/Products/Download/?type=xcj 1.M ...

  9. [转帖]Mysql 最简单的参数调优配置

    http://blog.jobbole.com/113659/ 我并不期望成为一个专家级的 DBA,但是,在我优化 MySQL 时,我推崇 80/20 原则,明确说就是通过简单的调整一些配置,你可以压 ...

随机推荐

  1. 使用 Nginx 内置 $http_user_agent 来区分( 电脑 pc、手机 mobile、平板 pad )端的内容访问

    location / { #pc端内容访问 set $flag "pc"; set $num 1; set $hua "${http_user_agent}"; ...

  2. shell脚本中如何插入其它脚本?

    答: 示例如下: #!/bin/sh . added.sh #include other script echo "hello"

  3. Python类元编程初探

    在<流畅的Python>一书中提到: Classes are first-class object in Python, so a function can be used to crea ...

  4. P4705 玩游戏

    思路 超级麻烦... 写了一堆最后常数太大T飞了... 真的难受 发现solve函数可以不用把下一层复制上来,直接传指针就可以,下次再说写不写叭 思路 \[ ans_k=\sum_{i=1}^n\su ...

  5. d3-tip中show在自己调用时需要改变this值

    <script src="https://d3js.org/d3.v4.min.js"></script><script src="http ...

  6. 使用ffmpeg进行视频封面截取

    项目需求:用户上传视频格式的文件,需要转为指定编码的MP4格式(为了适应在线播放),并且截取视频的第一帧作为封面图片(用于展示) 实现: 1.下载ffmpeg.exe 地址:http://ffmpeg ...

  7. kotlin 委托

    委托模式是软件设计模式中的一项基本技巧.在委托模式中,有两个对象参与处理同一个请求,接受请求的对象将请求委托给另一个对象来处理. Kotlin 直接支持委托模式,更加优雅,简洁.Kotlin 通过关键 ...

  8. Kotlin 数据类与密封类

    数据类 Kotlin 可以创建一个只包含数据的类,关键字为 data: data class User(val name: String, val age: Int) 编译器会自动的从主构造函数中根据 ...

  9. HTTP响应 状态码描述

  10. structure

    https://wenku.baidu.com/view/a82b12d62dc58bd63186bceb19e8b8f67c1cef04.html?sxts=1541829436140