一条SQL语句,正常执行时候特别快,但有时会变得特别慢,且这种情况很难复现,随机且持续时间很短,看上去像是“抖”了一下。

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

在MySQL 02中,介绍了WAL机制,InnoDB在处理更新语句时,更新内存写完redo log后,就返回给客户端,本次更新成功。

而内存里的数据最后要写入磁盘,这个操作称为flush。当内存数据页跟磁盘数据页内容不一致时,称这个内存页为脏页,内存数据写入磁盘后两者上的数据页内容一致,称为干净页。不论脏页还是干净页,都是指的内存中的数据页。

对于开头提出的场景,平时执行很快的更新操作,其实就是在写内存和日志,而“抖”的瞬间,很有可能就是在flush脏页。

有几种情况会引发数据库的flush过程:

  • InnoDB的redo log写满,这时候系统会停止所有的更新操作,通过flush把redo log中的checkpoint往前推进,使得redo log能有空间可以继续写;

  • 系统内存不足。当需要新的内存页,而内存不够用,就需要淘汰一些数据页,空出内存给别的数据页。如果要淘汰的是脏页,就需要先将脏页刷到磁盘。可能会问,这种情况为什么不能直接淘汰内存,下次请求时从磁盘读入数据页,然后应用redo log?这里是从性能考虑的,对于刷脏页写盘的方法,保证每个数据页有两种状态:

    • 内存里存在,肯定是正确结果,能直接返回;

    • 内存里不存在,磁盘中肯定是正确结果,读入内存后返回。

  • MySQL认为系统“空闲”,有机会就会进行flush;

  • MySQL正常关闭时,会把内存的脏页都flush到磁盘,这样下次MySQL启动时,直接从磁盘读数据即可,启动速度很快。

分析上述四种情况对性能的影响:

  • 第一种情况要尽量避免,因为这种情况下整个系统不能再更新,从监控上看更新数会跌为0;

  • 第二种情况较常见。在InnoDB中,用缓冲池(buffer pool)管理内存,缓冲池中的内存页有三种状态:

    • 还没有使用;

    • 使用了且是干净页;

    • 使用了且是脏页;

    由于InnoDB策略是尽量使用内存,因此对于一个长时间运行的库来说,未被使用的页面很少。如果要读入的数据页不在内存中,就需要在缓冲池申请一个数据页,把内存中最久未使用的数据页淘汰。如果淘汰的是脏页,就需要先flush。

    而如果一个查询要淘汰的脏页个数太多,会导致查询的响应时间明显变长,会明显影响性能

  • 第三种情况,系统没什么压力;

  • 第四种情况,数据库本身就要关闭了,不需要太关注性能问题。

InnoDB刷脏页的控制策略

接下来讲讲控制策略,以及和策略相关的参数。

首先,需要正确告诉InnoDB所在主机的IO能力,这样InnoDB才能知道需要全力刷脏页的时候可以刷多快。这需要用到innodb_io_capacity参数,它会告诉InnoDB你的系统的磁盘能力,其值建议设置成磁盘的IOPS,而磁盘的IOPS可以通过fio工具进行测试。

知道了“全力刷脏页”的能力,但使用时不可能一直全力刷,毕竟磁盘能力不能只用来刷脏页,还需要服务用户请求。因此,需要让InnoDB控制引擎按照“全力”的一定百分比来刷页。

那么,如果设计策略控制刷脏页的速度,你会考虑哪些因素呢?考虑到如果刷太慢,内存中脏页数会太多,且redo log可能写满,因此主要参考因素就是:

  • 脏页比例;

  • 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之间的数字,\(N\)越大算出来的值\(F2(N)\)越大。

根据两个数字\(F1(M)\)和\(F2(N)\),取其中较大的值记为\(R\),之后引擎可以按照innodb_io_capacity定义的能力乘以\(R\)%来控制刷脏页的速度。

上述过程的流程如图:

讲到这里你应该知道,无论是查询语句在需要内存的时候可能要求淘汰一个脏页,还是由于刷脏页会占用IO资源影响更新语句,都可能感知到MySQL“抖了一下。要尽量避免这种情况,就需要合理设置innodb_io_capacity的值,并且平时要多关注脏页比例,不要让它经常接近75%。

其中,脏页比例计算方法是Innodb_buffer_pool_pages_dirty/Innodb_buffer_pool_pages_total

接下来,再看一个策略。

一旦一个查询请求需要在执行过程中先 flush 掉一个脏页时,这个查询就可能要比平时慢了。MySQL中有个机制,可能让查询更慢:在准备刷一个脏页的时候,如果这个数据页旁边的数据页也是脏页,就会把这个“邻居”也带着一起刷掉,那么可能不断往后顺延。

在InnoDB中,用innodb_flush_neighbors参数控制该行为,值为1会有上述机制。

这类优化在机械磁盘时代比较有意义,可以减少很多随机IO。而对IOPS比较高的设备比如SSD,建议把值设为0,因为这时候IOPS往往不是瓶颈,而只刷自己能更快执行完必要的刷脏页操作,减少SQL语句响应时间。

在MySQL 8.0中,该参数默认值已经为0了。

MySQL 12 为什么我的MySQL会“抖”一下?的更多相关文章

  1. 12 | 为什么我的MySQL会“抖”一下? 学习记录

    <MySQL实战45讲>12 | 为什么我的MySQL会“抖”一下? 学习记录 http://naotu.baidu.com/file/15aa54cab2fa882c6a2a1dd52e ...

  2. Ubuntu 12.04上安装MySQL并运行

    Ubuntu 12.04上安装MySQL并运行 作者:凯鲁嘎吉 - 博客园 http://www.cnblogs.com/kailugaji/ 安装MySQL数据库 sudo apt-get upda ...

  3. Navicat Premium 12连接ubuntu18 ,Mysql 5.7.27-0

    1,搭建好mysql服务器,cd  /etc/mysql/mysql.conf.d,进入mysql配置目录,vim mysqld.cnf 2,注释掉,bind-address =127.0.0.1 , ...

  4. 【网站建设】Linux上安装MySQL - 12条命令搞定MySql

    从零开始安装mysql数据库 : 按照该顺序执行 :  a. 查看是否安装有mysql:yum list installed mysql*, 如果有先卸载掉, 然后在进行安装; b. 安装mysql客 ...

  5. Linux上安装MySQL - 12条命令搞定MySql

    从零开始安装mysql数据库 : 按照该顺序执行 :  a. 查看是否安装有mysql:yum list installed mysql*, 如果有先卸载掉, 然后在进行安装; b. 安装mysql客 ...

  6. Mysql学习总结(12)——21分钟Mysql入门教程

    21分钟 MySQL 入门教程 目录 一.MySQL的相关概念介绍 二.Windows下MySQL的配置 配置步骤 MySQL服务的启动.停止与卸载 三.MySQL脚本的基本组成 四.MySQL中的数 ...

  7. MySQL and Postgres command equivalents (mysql vs psql)

    MySQL and Postgres command equivalents (mysql vs psql) 博客分类: Database   From: http://blog.endpoint.c ...

  8. 【转】MYSQL入门学习之七:MYSQL常用函数

    转载地址:http://www.2cto.com/database/201212/175864.html 一.数学函数  www.2cto.com           ABS(x)           ...

  9. Can't find file: './mysql/plugin.frm' (errno: 13)[mysql数据目录迁移错位]错误解决

    大概需要4个步骤,其中第1步通过service mysql stop停止数据库,第4步通过service mysql start启动数据库. 第2步移动数据文件,不知道是否为Ubuntu智能的原因,移 ...

  10. MySQL监控模板说明-Percona MySQL Monitoring Template for Cacti

    http://blog.chinaunix.net/uid-16844903-id-3535535.html https://www.percona.com/doc/percona-monitorin ...

随机推荐

  1. Greenplum数据库时间操作汇总

    Greenplum数据库时间操作与mysql有一些区别,汇总以往笔记记录下来. greenplum时间格式:'yyyy-mm-dd hh24:mi:ss.us'.'yyyy-mm-dd hh:mi:s ...

  2. python,批量修改文件后缀名

    比如,D盘test目录下有以下几个没有后缀的文件,需要修改为txt结尾 python代码如下 # python批量更换后缀名 import os import sys #需要修改后缀的文件目录 os. ...

  3. zabbix 之安装采坑记

    很久没有安装过zabbix,理论上应该是很简单,但是还是遇到好几个小问题,导致浪费了两个小时时间了要,特此记录一下 如果没有研发源码的能力,建议选择LTS版本 zabbix 4.0 官方安装文档: h ...

  4. Vue ElementUI 树表格

    树表格做懒加载-点击小箭头走接口 children为[]则使用hasChildren的true/false来判断是否有子节点,另,如果要做点击小箭头走接口必须加lazy及load <el-tab ...

  5. EFCore多数据库合并查询分页

    EFCore多数据库合并查询分页 参照:二个表的数据 如何做分页?_两个表排序分页_深圳市热心市民市民的博客-CSDN博客 基本情况介绍:由于系统迭代,部分收藏表在老系统的数据库,部分在新api接口的 ...

  6. 蒟蒻 AstralNahida 的码风

    前言 这里是蒟蒻 OIer AstralNahida 在 OI 中的码风的详细介绍. 个人认为码风相当清晰,供给各位参考. 约定 对于一些表示必要性的关键词,从 must 到 mustn't 排序如下 ...

  7. Dynamic adaptation to application sizes (DATAS) GC 策略

    现在大家的 .NET 程序基本都部署在如 K8S 这种容器化场景下.出于节约资源的考虑,往往我们还会限制每个实例占用的资源.不知道大家发现没有,在一些高并发的场景下,我们的程序会占用非常多的内存,内存 ...

  8. Java Annotation认知(包括框架图、详细介绍、示例说明)--转载

    转载地址:https://www.cnblogs.com/skywang12345/p/3344137.html

  9. 智表 ZCELL 插件快速入门指南(原创)

    一.认识智表 ZCELL 插件 智表 ZCELL 是一款免费的前端 EXCEL 插件,它凝聚了多年工作经验与成果,旨在为用户带来极致的操作体验.该插件具备诸多优势,如轻量体积小,在浏览器端效率高:使用 ...

  10. .NET 的全新低延时高吞吐自适应 GC - Satori GC

    GC 的 STW 问题 GC,垃圾回收器,本质上是一种能够自动管理自己分配的内存的生命周期的内存分配器.这种方法被大多数流行编程语言采用,然而当你使用垃圾回收器时,你会失去对应用程序如何管理内存的控制 ...