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)

大家都在看

  • mysql安装及主从复制配置

    一、安装 mysql8.0 下载mysql 安装包http://mirrors.sohu.com/mysql/MySQL-8.0/ wget http://mirrors.sohu…

    数据库 2023年5月24日
    093
  • 微信小程序二维码

    一、获取小程序码的三个接口 不同的接口对应不同的业务场景,接口B用的较多,接口C官方不推荐使用,也就是说根据需码量来决定选择A接口还是B接口。 (1)、接口 A: 适用于需要的码数…

    数据库 2023年6月6日
    0153
  • Java面试题(二)–MySQL

    1 存储引擎 1、简单描述一个Mysql的内部结构? MySQL的基本架构示意图:大体来说,MySQL可以分为 server层和 存储引擎层两部分。 ① server层包括连接器、…

    数据库 2023年6月16日
    0108
  • Javaweb07-三层架构(BaseDao)

    1、BaseDao 持久层业务接口实现类的公共父类,定义了jdbc操作数据库的所有公共方法,方便子类继承; import java.io.InputStream; import j…

    数据库 2023年6月16日
    0128
  • 基础知识,不是很了解的

    Java中方法参数传递方式是按值传递。对于基本类型(int a, long b),参数传递时传递的是值,例如int a = 5,传递的就是5。如果是引用类型,传递是指向具体对象内存…

    数据库 2023年6月14日
    0124
  • ATM系统开发(Java版)

    ATM系统Java模拟开发总结 ATM系统开发 技术点分析 1.面向对象编程 每个用户的账户都是一个对象,所以需要设计账户类Accent用于创建账户对象封装账户信息。 2.使用集合…

    数据库 2023年6月16日
    0104
  • 一篇文章带你掌握主流数据库框架——MyBatis

    一篇文章带你掌握主流数据库框架——MyBatis MyBatis 是一款优秀的持久层框架,它支持自定义 SQL、存储过程以及高级映射。 在之前的文章中我们学习了MYSQL和JDBC…

    数据库 2023年6月14日
    0137
  • 跑步与读书

    本文来自博客园,作者:ukyo–BlackJesus,转载请注明原文链接:https://www.cnblogs.com/ukzq/p/16746334.html Or…

    数据库 2023年6月11日
    0130
  • Java 考试系统项目源码 springboot mybaits vue.js 支持手机端考试

    新增功能:培训学习模块, PDF电子课程、视频课程、直播课程(自己搭建直播流服务器) 人脸识别(考试时验证,有开关)、补考开关 组建试卷:创建试卷,题目、类型、总分、及格分数、时长…

    数据库 2023年6月6日
    0115
  • ShardingSphere 云上实践:开箱即用的 ShardingSphere-Proxy 集群

    本次 Apache ShardingSphere 5.1.2 版本更新为大家带来了三大全新功能,其中之一即为使用 ShardingSphere-Proxy chart 在云环境中快…

    数据库 2023年6月16日
    0121
  • 关于.netcore即时生成缩略图踩的坑

    最近在开发一套系统,很多地方用到了缩略图,然而不同的地方用到的尺寸又不一样,上传的时候生成缩略图就没有意义了,因为你不知道会使用到哪些尺寸,于是想到即时生成的办法,前端判断图片是否…

    数据库 2023年6月9日
    0120
  • 处理mysql主从不同步问题

    问题描述:发现主库操作数据从库没有变动问题,可能原因是从库重启导致的无法同步问题。 排查思路: 1、查看主从复制状态 发现从库的IO 和SQL 进程都是no(正常状态应该是yes)…

    数据库 2023年5月24日
    0118
  • Stripe支付介绍在asp.net mvc中开发对接,图文加代码说明

    最近一个国外的电商项目,需要对接支付功能,国内的支付一般使用微信支付、支付宝、银联等等,但国际上一般使用Paypal、Skrill、BrainTree、Stripe等,经过内部综合…

    数据库 2023年6月14日
    0137
  • git 烂笔头

    触类旁通, 举一反&amp…

    数据库 2023年6月9日
    0115
  • 实现线程的两种方式

    实现Runnable接口如果当前类 不仅要继承其他类( 非Thread类), 还要实现多线程,那么 只能通过当前类实现 Runnable接口来 创建Thread类对象。 实现Run…

    数据库 2023年6月16日
    0140
  • day04-3服务器推送新闻

    多用户即时通讯系统04 4.编码实现03 4.7功能实现-服务器推送消息功能实现 4.7.1思路分析 服务器推送新闻,本质其实就是群发消息 在服务器启动一个独立线程,专门负责推送新…

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