所以平时执行很快的更新操作,其实就是在写内存和日志,而MySQL抖擞地那一下,可能就是在刷脏页(flush)。
领导又开始懵逼了
那何时会触发MySQL的flush呀?
想想店老板何时会把赊账记录落实到账本?
1 redo log写满
借条写满了,这时再有更多的撕葱们来赊账,老板必须放下手活,将借条上的记录擦掉一些,腾空间以继续记账。当然了,擦掉前也必须先将正确账目记录到账本。
用技术话语描述,就是InnoDB的redo log写满了。这时系统会停止所有更新操作,把checkpoint往前推进,redo log留出空间可以继续写。
- redo log状态图
checkpoint 不是随便往前修改一下位置的。比如上图,把checkpoint位置从CP ~ CP’
,就需要将两个点之间的日志(浅绿色部分),对应的所有脏页都flush。之后,write pos ~ CP’
就可再写redo log。
2 系统内存不足
可以这么理解,这天生意太好,要记的事太多,老板发现自己快记不住了,赶紧找出账本把撕葱这笔账先加进去。
当需要新的内存页,而内存不够用的时候,就要淘汰一些数据页,空出内存给别的数据页用。若淘汰的是“脏页”,就要先将脏页写到磁盘。
领导又开始好奇了
这时难道不能直接把内存淘汰掉,下次需要请求时,从磁盘读入数据页,然后拿redo log出来应用不就行了?
这里其实是从性能考虑。若刷脏页一定会写盘,就保证了每个数据页有两种状态:
-
内存里存在,内存里就肯定是正确的结果,直接返回
-
内存里无数据,就可以肯定数据文件上是正确的结果,读入内存后返回。
这样的效率最高。
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;
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数Java工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年Java开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,真正体系化!
由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新
如果你觉得这些内容对你有帮助,可以添加V获取:vip1024b (备注Java)
总结
大型分布式系统犹如一个生命,系统中各个服务犹如骨骼,其中的数据犹如血液,而Kafka犹如经络,串联整个系统。这份Kafka源码笔记通过大量的设计图展示、代码分析、示例分享,把Kafka的实现脉络展示在读者面前,帮助读者更好地研读Kafka代码。
麻烦帮忙转发一下这篇文章+关注我
(备注Java)**
[外链图片转存中…(img-1d1JG37F-1712040217031)]
总结
大型分布式系统犹如一个生命,系统中各个服务犹如骨骼,其中的数据犹如血液,而Kafka犹如经络,串联整个系统。这份Kafka源码笔记通过大量的设计图展示、代码分析、示例分享,把Kafka的实现脉络展示在读者面前,帮助读者更好地研读Kafka代码。
麻烦帮忙转发一下这篇文章+关注我
[外链图片转存中…(img-gGL2UZbG-1712040217032)]