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

1)InnoDB 在处理更新语句的时候与磁盘有关的操作是什么?

  • 写日志

2)这个日志叫作什么?

  • redo log(重做日志):也就是《孔乙己》里咸亨酒店掌柜用来记账的粉板

3)更新成功的标志是什么?

  • 更新内存写完 redo log ,返回给客户端。

做下类比的话,掌柜记账的账本是数据文件,记账用的粉板是日志文件(redo log),掌柜的记忆就是内存。

4)掌柜总要找时间把账本更新这个对应数据库里面的什么操作?

  • 把内存里的数据写入磁盘的过程。这个过程叫flush

5)在这个 flush 操作执行之前,孔乙己的赊账总额,跟掌柜手中账本里面的记录是一致的吗?

  • 不是,因为孔乙己今天的赊账金额还只在粉板上,而账本里的记录是老的,还没把今天的赊账算进去。

6)当内存数据页跟磁盘数据页内容不一致的时候,我们称这个内存页为什么?

  • 脏页

7)有脏页就有干净页,那什么是干净页呢?

  • 内存和磁盘上的数据页的内容一致时,这个内存页叫做干净页。

8)假设原来孔乙己欠账 10 文,这次又要赊 9 文。孔乙己赊账”的整个操作过程是怎样的?

9)平时执行很快的操作,其实是在干嘛?

  • 写内存和日志

10)经过上面所学,MySQL 偶尔“抖”一下的那个瞬间可能是在干嘛?

  • 在刷脏页(flush)

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

11.1)我们还是继续用咸亨酒店掌柜的这个例子,想一想:掌柜在什么情况下会把粉板上的赊账记录改到账本上?

  • 第一种场景是,粉板满了,记不下了

    • 这个场景,对应的就是 InnoDB 的 redo log 写满了.

  • 第二种场景是,这一天生意太好,要记住的事情太多,掌柜发现自己快记不住了,赶紧找出账本把孔乙己这笔账先加进去。

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

  • 第三种场景是,生意不忙的时候,或者打烊之后。这时候柜台没事,掌柜闲着也是闲着,不如更新账本。

    • 这种场景,对应的就是 MySQL 认为系统“空闲”的时候。当然,MySQL“这家酒店”的生意好起来可是会很快就能把粉板记满的,所以“掌柜”要合理地安排时间,即使是“生意好”的时候,也要见缝插针地找时间,只要有机会就刷一点“脏页”。

  • 第四种场景是,年底了咸亨酒店要关门几天,需要把账结清一下。这时候掌柜要把所有账都记到账本上,这样过完年重新开张的时候,就能就着账本明确账目情况了。

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

12)分析一下上面四种场景对性能的影响?

  • 第三种第四种场景我们不需要关注性能,我们主要来看第一种和第二种。

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

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

13)InnoDB是使用什么来管理内存的?

  • 缓冲池(buffer pool)

14)缓冲池中的内存页有哪三种状态?

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

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

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

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

15)当要读入的数据页没有在内存的时候,这时候该怎么办?

  • 到缓冲池中申请一个数据页

  • 这时候只能把最久不使用的数据页从内存中淘汰掉:如果要淘汰的是一个干净页,就直接释放出来复用;但如果是脏页呢,就必须将脏页先刷到磁盘,变成干净页后才能复用。

16)我们说刷脏页虽然是常态,但是出现哪两种情况,都是会明显影响性能的?

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

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

17)针对上面可能出现的性能影响,InnoDB做了哪些优化来避免?

  • 控制脏页比例

18)InnoDB 刷脏页的控制策略是什么?

  • 首先,你要正确地告诉 InnoDB 所在主机的 IO 能力,这样 InnoDB 才能知道需要全力刷脏页的时候,可以刷多快。

  • 这就要用到 innodb_io_capacity 这个参数了,它会告诉 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 

19)因为没能正确地设置 innodb_io_capacity 参数,而导致的性能问题有哪些?

  • 之前,就曾有其他公司的开发负责人说 MySQL 的写入速度很慢,TPS 很低,但是数据库主机的 IO 压力并不大。经过一番排查,发现罪魁祸首就是这个参数的设置出了问题。

  • 他的主机磁盘用的是 SSD,但是 innodb_io_capacity 的值设置的是 300。于是,InnoDB 认为这个系统的能力就这么差,所以刷脏页刷得特别慢,甚至比脏页生成的速度还慢,这样就造成了脏页累积,影响了查询和更新性能。

20)innodb_io_capacity的默认值是多少?

  • 200,所以如果主机磁盘用的是SSD,大家建议改为20000.

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

  • 这个问题可以这么想,如果刷太慢,会出现什么情况?首先是内存脏页太多,其次是 redo log 写满。

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

22)脏页比例上限参数是什么,默认值是多少?

  • innodb_max_dirty_pages_pct,默认值是 75%。

23)实际上引擎根据哪些数据来控制刷脏页的速度?

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

  • InnoDB 每次写入的日志都有一个序号,当前写入的序号跟 checkpoint 对应的序号之间的差值,我们假设为 N。InnoDB 会根据这个 N 算出一个范围在 0 到 100 之间的数字,这个计算公式可以记为 F2(N)。

  • 根据上述算得的 F1(M) 和 F2(N) 两个值,取其中较大的值记为 R,之后引擎就可以按照 innodb_io_capacity 定义的能力乘以 R%

24)上面学习我们可以知道造成你从业务端感知到 MySQL“抖”了一下的原因有哪些?

  • 你的查询语句在需要内存的时候可能要求淘汰一个脏页。

  • 刷脏页的逻辑会占用 IO 资源并可能影响到了你的更新语句。

25)开发的时候我们应该怎么做去避免mysql抖一下?

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

26)脏页比例是怎么得到的?

  • 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;

27)在准备刷一个脏页的时候,如果这个数据页旁边的数据页刚好是脏页,那mysql会怎么处理?

  • 一起刷掉,如果邻居的邻居也是,也一起刷掉。这个就特别影响性能了。

28)那我们可不可以让他别把邻居也干掉?

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

29)如果使用的是 SSD 这类 IOPS 比较高的设备的话,我们应该怎么做?

  • 把 innodb_flush_neighbors 的值设置成 0,因为这时候 IOPS 往往不是瓶颈,而“只刷自己”,就能更快地执行完必要的刷脏页操作,减少 SQL 语句响应时间。

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

30)一个内存配置为 128GB、innodb_io_capacity 设置为 20000 的大规格实例,正常会建议你将 redo log 设置成 4 个 1GB 的文件。但如果你在配置的时候不慎将 redo log 设置成了 1 个 100M 的文件,会发生什么情况呢?又为什么会出现这样的情况呢?

  • redo log是关系型数据库的核心啊,保证了ACID里的D。所以redo log是牵一发而动全身的操作 ,当内存数据页跟磁盘数据页不一致的时候,把内存页称为'脏页'。如果redo log 设置得太小,redo log写满.那么会涉及到哪些操作呢,我认为是以下几点: 1.把相对应的数据页中的脏页持久化到磁盘,checkpoint往前推 2.由于redo log还记录了undo的变化,undo log buffer也要持久化进undo log 3.当innodb_flush_log_at_trx_commit设置为非1,还要把内存里的redo log持久化到磁盘上 4.redo log还记录了change buffer的改变,那么还要把change buffer purge到idb 以及merge change buffer.merge生成的数据页也是脏页,也要持久化到磁盘 上述4种操作,都是占用系统I/O,影响DML,如果操作频繁,会导致'抖'得向现在我们过冬一样。 但是对于select操作来说,查询时间相对会更快。因为系统脏页变少了,不用去淘汰脏页,直接复用 干净页即可。还有就是对于宕机恢复,速度也更快,因为checkpoint很接近LSN,恢复的数据页相对较少 所以要控制刷脏的频率,频率快了,影响DML I/O,频率慢了,会导致读操作耗时长。

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

  1. MySQL 笔记整理(12) --为什么我的MySQL会“抖”一下?

    笔记记录自林晓斌(丁奇)老师的<MySQL实战45讲> (本篇内图片均来自丁奇老师的讲解,如有侵权,请联系我删除) 12) --为什么我的MySQL会“抖”一下? 断更了一段时间,因为这几 ...

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

    平时的工作中,不知道你有没有遇到过这样的场景,一条SQL语句,正常执行的时候特别快,但是有时也不知道怎么回事,它就会变得特别慢,并且这样的场景很难复现,它不只随机,而且持续时间还很短. 看上去,这就像 ...

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

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

  4. 《Mysql - 我的Mysql为什么会抖一下?》

    一: 抖一下? - 平时的工作中,不知道有没有遇到过这样的场景. - 一条 SQL 语句,正常执行的时候特别快,但是有时也不知道怎么回事,它就会变得特别慢. - 并且这样的场景很难复现,它不只随机,而 ...

  5. Mysql的刷脏页问题

    平时的工作中,不知道你有没有遇到过这样的场景,一条 SQL 语句,正常执行的时候特别快,但是有时也不知道怎么回事,它就会变得特别慢,并且这样的场景很难复现,它不只随机,而且持续时间还很短. 当内存数据 ...

  6. MySQL实战45讲学习笔记:第十二讲

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

  7. 12 mysql性能抖动

    12 mysql性能抖动 sql语句为什么变”慢”了 在介绍WAL机制时,innodb在处理更新语句的时候,只做了写日志这一个磁盘操作,就是redo log,在更新内存写完redo log之后,就返回 ...

  8. 【Database】MySQL实战45讲

    01 | 基础架构:一条SQL查询语句是如何执行的? 1. MySQL 的基本架构图: MySQL可以分成: Server层 和 存储引擎层 两部分. Server层:包含连接器.查询缓存.分析器.优 ...

  9. MySQL重做日志(redo log)

    前面介绍了三种日志:error log.slow log.binlog,这三种都是 Server 层的.今天的 redo log 是 InnoDB引擎专有的日志文件. 为什么要有 redo log 用 ...

随机推荐

  1. bom-对话框

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

  2. ARC和MRC兼容和转换

    1.ARC模式下如何兼容非ARC的类 转变为非ARC -fno-objc-arc 转变为ARC的, -f-objc-arc (不常用) 2.如何将MRC转换为ARC

  3. 各种字体.效果和名字对应图. --- by 王朋

    原帖地址:http://www.oschina.net/question/565065_76244

  4. python 异常捕捉总结

    Process finished with exit code -1 错误 执行代码 pycharm2020.1中手动中断程序,可是却捕捉不了中断异常,并且输出Process finished wit ...

  5. python语法_1基础语法概述

    http://www.runoob.com/python3 章节:教程.基础语法.数据类型.解释器.注释.运算符. 大纲 查看python版本 实现第一个python3.x程序,hello world ...

  6. 如何综合运用对称加密技术、非对称加密技术(公钥密码体制)和Hash函数 保证信息的保密性、完整性、可用性和不可否认性?

    一.几个问题 在提出问题之前,先创建一个使用场景,发送方(甲方)要给接收方(乙方)发送投标书.大家知道,投标书都包括发送方的标的,这个标的是不能被竞标者知晓,更不能被竞标者修改的.在传输的投标书时,提 ...

  7. 关于sys.path.append()

    当我们导入一个模块时:import  xxx,默认情况下python解析器会搜索当前目录.已安装的内置模块和第三方模块,搜索路径存放在sys模块的path中: >>> import  ...

  8. 生产环境搭建高可用Harbor(包括恢复演练实操)

    生产环境搭建高可用Harbor(包括恢复演练实操) 前言 因资源成本问题,本Harbor高可用架构为最小开销方案,如果资源充足,可以将PG.Redis全部使用使用云厂商集群模式. 同时为了配置简单,并 ...

  9. Solution -「ARC 110F」Esoswap

    \(\mathcal{Description}\)   Link.   给定 \(0\sim n-1\) 的排列 \(p_{0..n-1}\),每次操作给出 \(i\),交换 \(p_i\) 和 \( ...

  10. Git简单介绍以及使用入门

    Git Git:分布式版本控制系统, 此外还有 SVN (集中式版本控制系统) 下载地址(阿里云镜像) :CNPM Binaries Mirror (npmmirror.com) Git Bash : ...