MySQL实战45讲 12

12 | 为什么我的MySQL会”抖”一下?

一条 SQL 语句,正常执行的时候特别快,但是 有时也不知道怎么回事,它就会变得特别慢,并且这样的场景很难复现,它不只随机,而且持续时间还很短。

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

内存里的数据写入磁盘的过程,叫做 flush。在这个 flush 操作执行之前,内存里的数据和磁盘里的是不一致的。

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

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

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

第一种场景是InnoDB 的redo log 写满了。这时候系统会停止所有更新操作,把 checkpoint 往前推进,redo log 留出空间可以继续写。

MySQL实战45讲 12

把 checkpoint 位置从 CP 推进到 CP’,就需要将两个点之间的日志(浅绿色部分),对应的所有脏页都 flush 到磁盘上。之后,图中从 write pos 到 CP’之间就是可以再写入的 redo log 的区域。

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

Q:如果直接淘汰内存,下次需要请求该页时,直接从磁盘读入数据页,然后拿 redo log 出来应用效率不好嘛?

A:

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

  • 一种是内存里存在, 内存里就肯定是正确的结果,直接返回;
  • 另一种是内存里没有数据,就可以肯定数据文件上是正确的结果,读入内存后返回。

这样的效率最高。

第三种场景是 MySQL 认为系统”空闲”的时候

第四种场景是 MySQL 正常关闭的情况。这时候,MySQL 会把内存的脏页都 flush 到磁盘上,这样下次 MySQL 启动的时候,就可以直接从磁盘上读数据,启动速度会很快。

上面四种场景对性能的影响

后两种情景不会太关注”性能”问题,主要来分析前两种场景下的性能问题。

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

第二种是”内存不够用了,要先将脏页写到磁盘”,这种情况其实是 常态

InnoDB 用缓冲池(buffer pool)管理内存,缓冲池中的内存页有三种状态:

  • 第一种是,还没有使用的;
  • 第二种是,使用了并且是干净页;
  • 第三种是,使用了并且是脏页。

InnoDB 的策略是尽量使用内存,因此对于一个长时间运行的库来说,未被使用的页面很少。

而当要读入的数据页没有在内存的时候,就必须到缓冲池中申请一个数据页。 这时候只能把最久不使用的数据页从内存中淘汰掉:

如果要淘汰的是一个干净页,就直接释放出来复用;

但如果是脏页, 就必须将脏页先刷到磁盘,变成干净页后才能复用

所以,刷脏页虽然是常态,但是出现 一个查询要淘汰的脏页个数太多,会导致查询的响应时间明显变长,明显影响性能

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

InnoDB 刷脏页的控制策略

首先,要正确地告诉 InnoDB 所在主机的 IO 能力,这样 InnoDB 才能知道需要 全力刷脏页的时候,可以刷多快。通过设置 innodb_io_capacity 这个参数为磁盘的 IOPS 来避免浪费磁盘性能。

毕竟磁盘能力不能只用来刷脏页,还需要服务用户请求。所以接下来,我们就一起看看 InnoDB 怎么控制引擎 按照”全力”的百分比来刷脏页

Q: 如果你来设计策略控制刷脏页的速度,会参考哪些因素呢?

A:

如果刷太慢,会出现什么情况?

首先是内存脏页太多,其次是 redo log 写满。

所以,InnoDB 的刷盘速度就是要参考这两个因素:一个是脏页比例,一个是 redo log 写盘速度。

参数 innodb_max_dirty_pages_pct 是 脏页比例上限,默认值是 75%。

F1:InnoDB 会根据当前的脏页比例(假设为 M),算出一个范围在 0 到 100 之间的F1

F2:InnoDB 每次写入的 日志都有一个序号,当前写入的序号跟 checkpoint 对应的序号之间的 差值为 N。InnoDB 会根据这个 N 算出一个范围在 0 到 100 之间的数字F2

根据上述算得的 F1 和 F2两个值,取其中较大的值记为 R,之后引擎就可以按照 innodb_io_capacity 定义的能力乘以 R% 来控制刷脏页的速度。

MySQL实战45讲 12

总结:

合理地设置 innodb_io_capacity 的值,并且 平时要多关注脏页比例,不要让它经常接近 75%

一个有趣的策略

一旦一个查询请求需要在执行过程中先 flush 掉一个脏页时,这个查询就可能要比平时慢了。而 MySQL 中的一个机制,可能让你的查询会更慢:

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

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

在 MySQL 8.0 中,innodb_flush_neighbors 参数的默认值是 0

Q:一个内存配置为 128GB、innodb_io_capacity 设置为 20000 的大规格实例,正常会建议你将 redo log 设置成 4 个 1GB 的文件。

但如果你在配置的时候不慎将 redo log 设置成了 1 个 100M 的文件,会发生什么情况呢?又为什么会出现这样的情况呢?

A:

每次事务提交都要写 redo log,如果设置太小,很快就会被写满,也就是下面这个图的状态,这个”环”将很快被写满, write pos 一直追着 CP

MySQL实战45讲 12

这时候系统不得不停止所有更新,去推进 checkpoint。

这时,看到的现象是 磁盘压力很小,但是数据库出现间歇性的性能下跌。

Original: https://www.cnblogs.com/ydssx7/p/16515461.html
Author: ydssx
Title: MySQL实战45讲 12

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/621048/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

  • Zabbix自带模板监控MySQL服务

    Zabbix的服务端与客户端的安装这里不再赘述了,前面也有相应的文章介绍过了,感兴趣的伙伴们可以看看历史文章就可以了,今天主要介绍下如何利用zabbix自带的模板来监控MySQL服…

    数据库 2023年6月9日
    0112
  • 记录一次数据库CPU被打满的排查过程

    1 前言 近期随着数据量的增长,数据库CPU使用率100%报警频繁起来。第一个想到的就是慢Sql,我们对未合理运用索引的表加入索引后,问题依然没有得到解决,深入排查时,发现在 or…

    数据库 2023年5月24日
    0110
  • 19-TCP、UDP的区别和应用场景

    可靠性TCP 提供交付保证,这意味着一个使用TCP协议发送的消息是保证交付给客户端的,如果消息在传输过程中丢失,那么它将重发。UDP是不可靠的,它不提供任何交付的保证,一个数据包在…

    数据库 2023年6月16日
    097
  • Centos7 离线安装K3s

    1、安装前准备 github地址:https://github.com/k3s-io/k3s/releases k3s二进制文件:k3s下载地址:github地址 / 百度网盘地址…

    数据库 2023年6月14日
    0105
  • zabbix监控用户,模组管理

    zabbix用户模组管理 用户管理 用户组 用户角色 用户 模板管理 模板组 模板 模板的监控项的参数也可以copy来 加入触发器 导出模板查看格式 posted @2022-09…

    数据库 2023年6月14日
    055
  • 使用REST风格完成MVC前后端分离

    一个具有REST风格项目的基本特征: 使用REST框架实现前后端分离架构,我们需要首先确定返回的JSON响应结构是统一的,也就是说,每个REST请求将返回相同结构的JSON响应结构…

    数据库 2023年6月11日
    0107
  • 如何利用bat文件伪装成木马病毒整蛊他人

    bat文件是dos下的批处理文件。批处理文件是无格式的文本文件,它包含一条或多条命令。它的文件扩展名为 .bat 或 .cmd。 将以下代码复制到文本文档中,保存后修改文件后缀名称…

    数据库 2023年6月11日
    098
  • [Mysql]Ubuntu如何安装Mysql+启用远程连接[完整版]

    唉。下面是我花了不知道多少个小时踩过的所有坑总结出来的血泪史,希望能帮你们少踩一些坑吧,正常来讲一步一步下来就不会出现任何问题了。 背景 用的是百度云的云服务器(其他云服务器同理)…

    数据库 2023年6月16日
    080
  • 2_Git

    一. 引言 在单人开发过程中, 需要进行版本管理, 以利于开发进度的控制 在多人开发过程中, 不仅需要版本管理, 还需要进行多人协同控制 二. 介绍 Git是一个 开源的分布式版本…

    数据库 2023年6月11日
    088
  • 详谈 MySQL 8.0 原子 DDL 原理

    柯煜昌 青云科技研发顾问级工程师 目前从事 RadonDB 容器化研发,华中科技大学研究生毕业,有多年的数据库内核开发经验。 文章字数 3800+,阅读时间 15 分钟 背景 My…

    数据库 2023年6月11日
    0141
  • 2022-8-18 第六组 JDBC

    JDBC 1. 概念:Java DataBase Connectivity Java 数据库连接, Java语言操作数据库 JDBC本质:其实是官方(sun公司)定义的一套操作所有…

    数据库 2023年6月14日
    082
  • cron 表达式

    cron 表达式 1.简介:一个cron表达式最少有5个空格来分割时间元素,总共有7个元素,分别如下: ① 秒(0-59) ② 分钟(0-59) ③ 小时(0-23) ④ 天(月的…

    数据库 2023年6月16日
    097
  • 6_SSM

    一. ssm整合 1.1 项目创建 1.1.1 创建Maven项目 创建一个普通的Maven-web项目,名称为ssm 记得勾选上Create from archetype然后选择…

    数据库 2023年6月11日
    074
  • Python–软件目录结构

    目的不必多说:提高项目可读性、可维护性 软件目录结构示例: 那么问题来了,当类似于如上的目录结构时,我怎么在game.py中去调用setting.py或者main.py中的函数呢?…

    数据库 2023年6月9日
    083
  • PHP获取前一天,前一个月,前半年,前一年的时间戳

    // 获取前一秒 strtotime("-1 seconds"); // 获取前一分钟 strtotime("-1 minute"); //…

    数据库 2023年6月14日
    0129
  • 【转】IDEA一键部署SpringBoot项目到服务器

    原文连接:https://www.cnblogs.com/chanmufeng/p/15926928.html 1. 安装Alibaba Cloud Toolkit插件 2. 配置…

    数据库 2023年6月6日
    085
亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球