程序员写bug导致MySQL线上事故赔款百万,第二天就被CTO开除了!

2 系统内存不足

可以这么理解,这天生意太好,要记的事太多,老板发现自己快记不住了,赶紧找出账本把撕葱这笔账先加进去。

当需要新的内存页,而内存不够用的时候,就要淘汰一些数据页,空出内存给别的数据页用。若淘汰的是“脏页”,就要先将脏页写到磁盘。

领导又开始好奇了

这时难道不能直接把内存淘汰掉,下次需要请求时,从磁盘读入数据页,然后拿redo log出来应用不就行了?

这里其实是从性能考虑。若刷脏页一定会写盘,就保证了每个数据页有两种状态:

  1. 内存里存在,内存里就肯定是正确的结果,直接返回

  2. 内存里无数据,就可以肯定数据文件上是正确的结果,读入内存后返回。

这样的效率最高。

3 MySQL认为系统“空闲”时

生意不忙时自然没啥忙的,店老板也闲着,不如更新下账本。

MySQL空闲机会总是少的,可能很快把日志写满,所以MySQL要合理安排时间,即使很忙,也要见缝插针地找时间,只要有机会就刷一点“脏页”。

4 MySQL正常关闭

年底要关门回家过年了,清算账目。

这时候掌柜要把所有账都记到账本上,这样过完年重新开张的时候,就能就着账本明确账目情况了。

这时MySQL会把内存的脏页都flush,下次启动时,就能直接从磁盘读数据,启动速度会很快。

领导开始犯难了,这么多场景都会触发,它们会对线上稳定性有啥影响吗?

各场景的性能开销

=======================================================================

第3种MySQL空闲时的操作,系统本就无压力,第4种MySQL还本来就要关闭了。所以这两种情况你也都不会去关注性能。

第1种:“redo log写满,要flush脏页”,这种情况是InnoDB要尽量避免的。因为此时,整个系统就不能再接受更新,所有更新都必须堵住。

从监控上看,这时更新数会跌为0。

第2种:“内存不够了,要先将脏页flush”,这种情况其实就是常态。InnoDB用缓冲池(buffer pool)管理内存,缓冲池中的内存页有如下状态

  • 还没有使用的

  • 使用了并且是干净页

  • 使用了并且是脏页。

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

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

  • 干净页

直接释放出来复用

  • 脏页

必须将脏页先刷盘,变干净后才能复用

所以,刷脏页虽然是常态,但出现以下这两种情况,都会明显影响性能:

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

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

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

哦豁,只见领导又放大了眼睛,愿闻其详,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

由于错误设置innodb_io_capacity参数导致的性能问题很多。比如,有时一个库的性能,可能MySQL的写入速度很慢,TPS很低,但数据库主机的IO压力并不大。

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

虽然我们现在已经定义了“全力刷脏页”的行为,但平时总不能一直是全力刷,毕竟磁盘能力不能只用来刷脏页,还需要服务用户请求。

InnoDB怎么控制引擎按照“全力”的百分比来刷脏页。

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

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

  • 内存脏页太多

  • redo log写满

所以,InnoDB的刷盘速度就是要参考这两个因素:一个是脏页比例,一个是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之间的数字,这个计算公式可以记为F2(N),N越大,算出来的值越大。

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

F1、F2就是通过脏页比例和redo log写入速度算出来的两个值。

  • InnoDB刷脏页速度策略

InnoDB会在后台刷脏页,而刷脏页过程要将内存页落盘。所以,无论是你的查询语句在需要内存时可能要求淘汰一个脏页,还是由于刷脏页的逻辑会占用IO资源并可能影响到你的更新语句,都可能导致MySQL抖动。

要尽量避免这种情况,就要合理配置innodb_io_capacity,日常也要多关注脏页比例,不要让它经常接近75%

其中,脏页比例是通过

总结

我个人认为,如果你想靠着背面试题来获得心仪的offer,用癞蛤蟆想吃天鹅肉形容完全不过分。想必大家能感受到面试越来越难,想找到心仪的工作也是越来越难,高薪工作羡慕不来,却又对自己目前的薪资不太满意,工作几年甚至连一个应届生的薪资都比不上,终究是错付了,错付了自己没有去提升技术。

这些面试题分享给大家的目的,其实是希望大家通过大厂面试题分析自己的技术栈,给自己梳理一个更加明确的学习方向,当你准备好去面试大厂,你心里有底,大概知道面试官会问多广,多深,避免面试的时候一问三不知。

大家可以把Java基础,JVM,并发编程,MySQL,Redis,Spring,Spring cloud等等做一个知识总结以及延伸,再去进行操作,不然光记是学不会的,这里我也提供一些脑图分享给大家:

希望你看完这篇文章后,不要犹豫,抓紧学习,复习知识,准备在明年的金三银四拿到心仪的offer,加油,打工人!
ring cloud等等做一个知识总结以及延伸,再去进行操作,不然光记是学不会的,这里我也提供一些脑图分享给大家:

[外链图片转存中…(img-D673SNja-1720123814886)]

[外链图片转存中…(img-b1bLx9Xk-1720123814887)]

[外链图片转存中…(img-WFgje8HZ-1720123814887)]

希望你看完这篇文章后,不要犹豫,抓紧学习,复习知识,准备在明年的金三银四拿到心仪的offer,加油,打工人!

  • 10
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值