笔记记录自林晓斌(丁奇)老师的《MySQL实战45讲》

(本篇内图片均来自丁奇老师的讲解,如有侵权,请联系我删除)

12) --为什么我的MySQL会“抖”一下?

  断更了一段时间,因为这几周实在是太忙了,周末加班两天那种。。。

  有时你会遇到这样的问题,一条SQL语句,正常执行的时候很快,但是有时候会变得特别慢。并且这种场景很难复现,不只随机而且持续时间很短。这其实与MySQL的脏页以及它的刷新机制有关。之前我们有过一个关于《孔乙己》里面酒馆老板记账的比喻。在这个比喻里,掌柜的账本就是我们的数据文件,掌柜的临时写下的粉板就是我们的日志文件(redo log),而掌柜的记忆就相当于我们的内存。

  粉板可以记录的内容有限(redo log循环写),掌柜的记忆也是有限的,因此他总要找时间把这两部分的内容记录到账本里去。这个术语就是flush.

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

  大致上有四种情景来进行刷“脏页”:

  1. 粉板满了。(redo log写满),redo log写满以后,如果又有了新的数据,就不得不去除一些之前的数据。当然,在去除之前,要先把正确的数据记录下来才行。
  2. 生意太好,短时间内有很多客人,掌柜的记不下来了。(系统内存不足)。内存不足时,需要先淘汰掉一些数据页,如果这些数据页中有“脏页”就必须要把这些记录到磁盘才行。你可能会有疑问,为什么不直接淘汰掉这些页呢,如果再有相关的记录,就利用redo log来还原数据呢?(掌柜的疑问一部分脑子里的记忆,下次再有的话,先看账本,然后再看粉板,倒退出最新的记录),这其实是从性能方面考虑的。如果我们保证每次刷脏页一定会写磁盘,那么下次再读的时候就有两种情况。一是内存中有记录,那么直接返回。二是,内存中没有,那么先从磁盘读,读到了就直接返回。对应掌柜的就是,掌柜的有印象,直接返回。掌柜的没有印象查看账本,找到了就直接返回。
  3. 生意不太忙的时候,掌柜的闲着没事,就更新账本。(系统空闲),闲着没事,Mysql就自己刷脏页玩。
  4. 年底放假,酒店关门几天。(MySQL正常关闭),正常关闭时MySQL会把内存的脏页都flush到磁盘上。

  回到我们开始的问题,什么情况会抖一下呢?首先排除后两种,空闲或是要关闭数据库时。来看看前两种情况:

  先是redo log写满了,要flush脏页,这种情况是InnoDB要尽量避免的。因为这种情况下,整个系统就不能再接受更新了,所有的更新都必须堵住。如果你从监控上看,这时的更新数会跌为0.然后是第二种情况:“内存不够用了,要先将脏页写到磁盘”。这种情况是常态。InnoDB用缓冲池(buffer pool)管理内存,缓冲池中的内存页有三种状态:

  1. 还没使用的
  2. 使用了并且是干净页的
  3. 使用了并且是脏页的  

  InnoDB的策略是尽量使用内存,因此对于一个长时间运行的库来说,未被使用的页面很少。当要读入的数据页没有在内存的时候,就必须到缓冲池中申请一个数据页。这时候只能把最久不使用的数据页从内存中淘汰掉。如果淘汰掉的是一个干净页,可以直接释放出来复用。如果淘汰掉的是一个脏页,就必须先将脏页刷到磁盘,变成干净页后才能复用。所以,刷脏页虽然是常态,但是出现以下两种情况,都会明显的影响性能:

  1. 一个查询要淘汰的脏页太多,会导致查询的响应时间明显变长
  2. 日志写满,更新全部堵住,写性能跌为0,这个情况对敏感业务来说,是不能接受的。

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

InnoDB刷脏页的控制策略

  首先,你要正确地告诉InnoDB所在主机的IO能力,这样InnoDB才能知道需要全力刷脏页的时候,可以刷多快。这个就要用到innodb_io_capacity这个参数了,它会告诉InnoDB你的磁盘能力。这个值建议你设置为磁盘的IOPS,磁盘的IOPS可以通过fio(linux)来进行测试。(Linux下fio,window下可以使用iometer)

  InnoDB使用两个因素来进行计算刷盘速度。一个是脏页比例,一个是redo log的写盘速度。参数innodb_max_dirty_pages_pct是脏页比例上限,默认值是75%。InnoDB会根据当前的脏页比例M,算出一个范围在0到100之间的数字。InnoDB每次写入日志都有一个序号,当前写入的序号跟checkpoint对应的序号之间的差值,我们假设为N,同样,InnoDB会根据这个N算出一个0到100之间的数字。N越大这个计算出来的值就越大。然后,根据上述两个计算出的数据f(M)和f(N),取其中较大的值记为R,之后引擎就可以按照innodb_io_capacity定义的能力乘以R%来控制刷脏页的速度了。

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

  还有一个有趣的策略:一旦一个请求涉及到刷脏页,在准备进行刷脏页的时候,会把这个数据页旁边的数据页也检查一下,如果这个邻居也是脏页,那么就会把邻居一起刷掉。InnoDB使用参数innodb_flush_neighbors参数来控制这个行为,为1的时候就会触发这个“连坐”机制。在MySQL8.0中,这个默认值已经是0了。

上期问题:

  如果你要维护学生信息的数据库,学生登录名统一是"学号@gamail.com",学号的规则是十五位的数字,前三位是城市编号,四到六位是学校编号,七到十位是入学年份,最后五位是顺序编号,只考虑登录验证的话,你会怎么设计这个登录名的索引呢?

  由于这个学号的规则,无论是正向还是反向的前缀索引,重复度都很高。前三位是城市编号,四到六位是学校编号,这六位数字其实是相对固定的。而邮箱后缀也是确定的,因此可以只存入学年份加顺序编号,它们的长度是9位。在此基础上,可以用数字类型来存储这个9位数字,这样只需占用4个字节,这其实是一种hash,只是用了最简单的转换规则。

  另有别的思路是,一个学校总人数不会很大,这点数据量,这个表必然是个小表。直接存原来的字符串,可以使业务更简单。这也是一种很好的回答,结合实际业务。

问题:

  一个内存配置为128GB,innodb_io_capacity设置为20000的大规格实例,正常会建议你将redo log设置成4个1GB的文件,但是如果你配置时不小心将redo log设置为了4个100M的文件,会发生什么情况呢?为什么呢?

MySQL 笔记整理(12) --为什么我的MySQL会“抖”一下?的更多相关文章

  1. 最全mysql笔记整理

    mysql笔记整理 作者:python技术人 博客:https://www.cnblogs.com/lpdeboke Windows服务 -- 启动MySQL net start mysql -- 创 ...

  2. MySQL 笔记整理(1) --基础架构,一条SQL查询语句如何执行

    最近在学习林晓斌(丁奇)老师的<MySQL实战45讲>,受益匪浅,做一些笔记整理一下,帮助学习.如果有小伙伴感兴趣的话推荐原版课程,很不错. 1) --基础架构,一条SQL查询语句如何执行 ...

  3. MySQL笔记(七)远程连接MySQL

    mysql 默认只允许 localhost 连接,因此在远程连接服务器上的 mysql 之前,需要做一些设置.在没有设置前,默认是下面的状况,mysql 只能由 localhost(127.0.0.1 ...

  4. MySQL 笔记整理(16) --“order by”是怎么工作的?

    笔记记录自林晓斌(丁奇)老师的<MySQL实战45讲> (本篇内图片均来自丁奇老师的讲解,如有侵权,请联系我删除) 16) --“order by”是怎么工作的? 在林老师的课程中,第15 ...

  5. MySQL 笔记整理(19) --为什么我只查一行的语句,也执行这么慢?

    笔记记录自林晓斌(丁奇)老师的<MySQL实战45讲> (本篇内图片均来自丁奇老师的讲解,如有侵权,请联系我删除) 19) --为什么我只查一行的语句,也执行这么慢? 需要说明一下,如果M ...

  6. MySQL 笔记整理(18) --为什么这些SQL语句逻辑相同,性能却差异巨大?

    笔记记录自林晓斌(丁奇)老师的<MySQL实战45讲> (本篇内图片均来自丁奇老师的讲解,如有侵权,请联系我删除) 18) --为什么这些SQL语句逻辑相同,性能却差异巨大? 本篇我们以三 ...

  7. MySQL 笔记整理(17) --如何正确地显示随机消息?

    笔记记录自林晓斌(丁奇)老师的<MySQL实战45讲> (本篇内图片均来自丁奇老师的讲解,如有侵权,请联系我删除) 17) --如何正确地显示随机消息? 如果有这么一个英语单词表,需要每次 ...

  8. MySQL 笔记整理(14) --count(*)这么慢,我该怎么办?

    笔记记录自林晓斌(丁奇)老师的<MySQL实战45讲> (本篇内图片均来自丁奇老师的讲解,如有侵权,请联系我删除) 14) --count(*)这么慢,我该怎么办? 有时你会发现,随着系统 ...

  9. MySQL 笔记整理(13) --为什么数据表删掉一半,表文件大小不变?

    笔记记录自林晓斌(丁奇)老师的<MySQL实战45讲> (本篇内图片均来自丁奇老师的讲解,如有侵权,请联系我删除) 13) --为什么数据表删掉一半,表文件大小不变? 我们还是以MySQL ...

随机推荐

  1. 用Service+Broadcast解决倒计时过程中Activity被销毁的问题

    主要思想是这样的:将倒计时CountDownTimer放在Service里面进行,每过一秒就一条发广播,在主Activity里注册广播,收到广播后更新UI. 一.写一个类CodeTimerServic ...

  2. 部署Chart应用并使用.net core读取Kubernetes中的configMap

    上一篇文章讲了 k8s使用helm打包chart并上传到腾讯云TencentHub,今天就讲一下使用Helm部署应用并使用configMap代替asp.net core 中的appsettings.j ...

  3. javascript模块化编程 从入门到实战

    <!DOCTYPE html> <html lang="zh-cn"> <head> <meta charset="UTF-8& ...

  4. Bagging之随机森林

    随机森林(Random Forest)是一种Bagging(Bootstrap Aggregating)集成算法,在样本随机(样本扰动)的基础上,进一步运用特征随机(属性扰动)的机制,得到比一般的Ba ...

  5. .NET Core IdentityServer4实战-开篇介绍与规划

    一.开篇寄语 由于假期的无聊,我决定了一个非常有挑战性的活动,也就是在年假给大家带来一个基于OAuth 2.0的身份授权框架,它就是 IdentityServer4 ,如果没有意外的话,一定可以顺利的 ...

  6. Shim 与 Polyfill

    Shim: 用来向后兼容.比如 requestIdleCallback,为了在旧的环境中不报错,可以加 shim. 使用环境中现有的 api 来实现,不会引入额外的依赖或其他技术. Polyfill: ...

  7. docker常规操作——启动、停止、重启容器实例

    一.启动一个已经停止的容器实例 docker start 容器ID或容器名,建议使用容器ID,容器ID支持模糊查询而容器名称不支持1. 先查看已经暂停的容器实例信息 2. 通过docker start ...

  8. PHP开发模式之-单例模式

    1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 class  Db{ private function __construct(){} private static ...

  9. 【推荐】桌面版AI伴侣 含2.47 2.49 2.51汉化版

    桌面版AI伴侣,无需安装aiStarter,直接运行bat就能在电脑上启动AI伴侣,启动速度比虚拟机快很多.缺点是对硬件的要求比较高. 文件来自 https://mp.weixin.qq.com/s/ ...

  10. Sql Server 本地(客户端)连接服务器端操作

    网有很多相关内容,我在此做记录和总结 1.主要是sql server 配置管理工具的配置 在此参考 https://www.cnblogs.com/yougmi/p/4616273.html(再次感谢 ...