你的 SQL 语句为什么变“慢”了

平时执行很快的更新操作,其实就是在写内存和日志,而 MySQL 偶尔“抖”一下的那个瞬间,可能就是在刷脏页(flush)。

当内存数据页跟磁盘数据页内容不一致的时候,我们称这个内存页为“脏页”。内存数据写入到磁盘后,内存和磁盘上的数据页的内容就一致了,称为“干净页”

什么情况会引发数据库的 flush 过程呢?

InnoDB 的 redo log 写满了

这时候系统会停止所有更新操作,把 checkpoint 往前推进,redo log 留出空间可以继续写,checkpoint 往前推进时,会把对应的所有脏页都 flush 到磁盘上

系统内存不足

当需要新的内存页,而内存不够用的时候,就要淘汰一些数据页,空出内存给别的数据页使用。如果淘汰的是“脏页”,就要先将脏页写到磁盘。

刷脏页一定会写盘,就保证了每个数据页有两种状态:

a. 一种是内存里存在,内存里就肯定是正确的结果,直接返回;

b.另一种是内存里没有数据,就可以肯定数据文件上是正确的结果,读入内存后返回。这样的效率最高。

MySQL 认为系统“空闲”的时候

MySQL 正常关闭的情况

MySQL 会把内存的脏页都 flush 到磁盘上,这样下次 MySQL 启动的时候,就可以直接从磁盘上读数据,启动速度会很快

四种场景对性能的影响

“redo log 写满了,要 flush 脏页”

这种情况是 InnoDB 要尽量避免的。因为出现这种情况的时候,整个系统就不能再接受更新了,所有的更新都必须堵住。如果你从监控上看,这时候更新数会跌为 0。

“内存不够用了,要先将脏页写到磁盘”

这种情况其实是常态。InnoDB 用缓冲池(buffer pool)管理内存,缓冲池中的内存页有三种状态:

a. 第一种是,还没有使用的;

b. 第二种是,使用了并且是干净页;

c. 第三种是,使用了并且是脏页。

InnoDB 的策略是尽量使用内存,因此对于一个长时间运行的库来说,未被使用的页面很少。而当要读入的数据页没有在内存的时候,就必须到缓冲池中申请一个数据页。这时候只能把最久不使用的数据页从内存中淘汰掉:如果要淘汰的是一个干净页,就直接释放出来复用;但如果是脏页呢,就必须将脏页先刷到磁盘,变成干净页后才能复用。

所以,刷脏页虽然是常态,但是出现以下这两种情况,都是会明显影响性能的:

a. 一个查询要淘汰的脏页个数太多,会导致查询的响应时间明显变长;

b. 日志写满,更新全部堵住,写性能跌为 0,这种情况对敏感业务来说,是不能接受的。

所以,InnoDB 需要有控制脏页比例的机制,来尽量避免上面的这两种情况。

InnoDB 刷脏页的控制策略

innodb_io_capacity 参数会告诉 InnoDB 你的磁盘能力,这样 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_max_dirty_pages_pct 参数是脏页比例上限,默认值是 75%。InnoDB 会根据当前的脏页比例(假设为 M),算出一个范围在 0 到 100 之间的数字 F1(M) ,InnoDB 每次写入的日志都有一个序号,当前写入的序号跟 checkpoint 对应的序号之间的差值,我们假设为 N。InnoDB 会根据这个 N 算出一个范围在 0 到 100 之间的数字 F2(N),根据上述算得的 F1(M) 和 F2(N) 两个值,取其中较大的值记为 R,之后引擎就可以按照 innodb_io_capacity 定义的能力乘以 R% 来控制刷脏页的速度。

InnoDB 会在后台刷脏页,而刷脏页的过程是要将内存页写入磁盘。所以,无论是你的查询语句在需要内存的时候可能要求淘汰一个脏页,还是由于刷脏页的逻辑会占用 IO 资源并可能影响到了你的更新语句,都可能是造成你从业务端感知到 MySQL“抖”了一下的原因

要尽量避免这种情况,你就要合理地设置 innodb_io_capacity 的值,并且平时要多关注脏页比例,不要让它经常接近 75%

其中,脏页比例是通过 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;

MySQL 在准备刷一个脏页的时候,如果这个数据页旁边的数据页刚好是脏页,就会把这个“邻居”也带着一起刷掉;而且这个把“邻居”拖下水的逻辑还可以继续蔓延,也就是对于每个邻居数据页,如果跟它相邻的数据页也还是脏页的话,也会被放到一起刷。

innodb_flush_neighbors 参数就是用来控制这个行为的,值为 1 的时候会有上述的“连坐”机制,值为 0 时表示不找邻居,自己刷自己的

找“邻居”这个优化在机械硬盘时代是很有意义的,可以减少很多随机 IO。机械硬盘的随机 IOPS 一般只有几百,相同的逻辑操作减少随机 IO 就意味着系统性能的大幅度提升。

而如果使用的是 SSD 这类 IOPS 比较高的设备的话,我就建议你把 innodb_flush_neighbors 的值设置成 0。因为这时候 IOPS 往往不是瓶颈,而“只刷自己”,就能更快地执行完必要的刷脏页操作,减少 SQL 语句响应时间。

在 MySQL 8.0 中,innodb_flush_neighbors 参数的默认值已经是 0 了。

mysql抖动可能的原因,12 | 为什么我的MySQL会“抖”一下?相关推荐

  1. mysql抖动可能的原因_MySQL应对网络抖动问题

    默认情况下,MySQL本身通过各种TIMEOUT参数来断开链接. 对TIMEOUT的各种解释: connect_timeout 在建立连接时起作用,对于使用连接池的情况或者网络较差的情况建议将该值增大 ...

  2. php连接mysql乱码原因_PHP连接MYSQL出现乱码的原因与解决办法

    PHP连接mysql出现乱码的原因与解决方法 解决MySql数据库乱码的一个首要前提是保证 数据库+数据表+前端显示 编码一致,国内项目一般统一设定为GB2312或GBK,而国际化项目则一般使用utf ...

  3. 关于linux系统下遇到的mysql问题_关于Linux系统上遇到的MySql有关问题,求指导

    关于Linux系统下遇到的mysql问题,求指导 问题1: Mysql是安装在linux体统中,操作是通过使用WindowsXP 下的软件Navicat 8 for MySQL,在连接上Linux中的 ...

  4. 12个MySQL慢查询的原因分析

    1. SQL 没加索引 很多时候,我们的慢查询,都是因为没有加索引.如果没有加索引的话,会导致全表扫描的.因此,应考虑在 where 的条件列,建立索引,尽量避免全表扫描. 反例: select * ...

  5. MySQL Connectors组件8.0.12及之前版本的Connector/J子组件存在安全漏洞及其相关性分析

    今天我把自己的SpringBoot项目上传到了GitHub,于是murphysec安全扫描平台扫描到了我的代码安全问题,如下 漏洞标题:Oracle MySQL Connectors组件访问控制错误漏 ...

  6. 高性能MySQL实战第12讲:海量数据MySQL项目实战

    你好,我是你的数据库老师周彦伟,欢迎来到第 10 课时"MySQL 亿级数据库项目实战",这是本系列课程的最后一课时,本课时的主要内容包含 MySQL 典型数据库架构介绍.MySQ ...

  7. mysql性能的介绍少_MySQL性能突然下降怎么回事 MySQL性能突然下降原因介绍

    MySQL性能突然下降怎么回事?本篇文章小编给大家分享一下MySQL性能突然下降原因介绍,小编觉得挺不错的,现在分享给大家供大家参考,有需要的小伙伴们可以来看看. 有时会碰到这样的情况,一条 SQL ...

  8. 「mysql优化专题」高可用性、负载均衡的mysql集群解决方案(12)

    不可避免的是,使用MySQL时随着时间的增长,用户量以及数据量的逐渐增加,访问量更是剧增,最终将会使MySQL达到某个瓶颈,那么MySQL的性能将会大大降低.怎么办?前面已经讲过十一篇优化方案,接下来 ...

  9. rds mysql 磁盘空间,RDS MySQL 空间问题的原因和解决

    other_size- 系统文件和临时文件使用空间 data_size- 数据文件使用空间 binlog_size- Binlog 文件占用空间 注:获取实例诊断报告的步骤请参考如何访问RDS 实例诊 ...

最新文章

  1. NDC 2010视频下载:看看其他微软平台程序员们都在做什么
  2. caffe依赖项安装
  3. Cpp 对象模型探索 / 编译器为对象创建缺省构造函数的条件
  4. 关于.NET5在IIS中部署的几个问题总结
  5. Spring Boot –如何跳过缓存thyemeleaf模板,js,css等以每次绕过重启服务器
  6. 数字社交圈里的白酒“新”消费——腾讯2021白酒行业数字营销洞察白皮书
  7. 新设计了自己博客的模板
  8. ASCII,Unicode,UTF-8,GB2312一些关于编码的理解
  9. 数据分析笔试题(网易,阿里,京东...)
  10. 图论(Tarjan算法与无向图)
  11. 免费好用的划词搜题神器插件
  12. Web前端html表格制作
  13. SL4A apk 编译生成
  14. linux计时器命令,安装及使用Linux终端倒数计时器Countdown的方法
  15. 小学生获奖作品html,小学生优秀绘画作品图片展示
  16. 《恐怖电脑》技术支持
  17. 平稳性检验和白噪声检验
  18. Java之日志打印占位符
  19. 开发Java程序的工具
  20. MODBUS通信协议代码

热门文章

  1. 巧用 Trie 树,实现搜索引擎关键词提示功能
  2. 你需要知道的那些 redis 数据结构(前篇)
  3. 那些中国式家庭的小烦恼,我看用AI来解决就“都挺好” | 技术头条
  4. python 抽象语法树_用python演示一个简单的AST(抽象语法树)
  5. 北语18春《计算机网络技术》作业4,北语18春《计算机网络技术》作业4
  6. linux死锁的例子,操作系统教程—Linux实例分析 孟庆昌 第8章 死锁new.ppt
  7. 宿主机进程挂载到容器内_迄今为止最严重的容器逃逸漏洞:Docker cp命令漏洞分析(CVE201914271)...
  8. cxf javax.xml.parsers.DocumentBuilderFactory.setFeature(Ljava/lang/String;Z)
  9. 创新小组 实战Git团队企操作手册_精华版本
  10. String类、StringBuffer类、StringBuilder类的区别