redo log⼤家都知道,也就是我们对数据库操作的⽇志,他是在内存中的,每次操作⼀旦写了redo log就
会⽴⻢返回结果,但是这个redo log总会找个时间去更新到磁盘,这个操作就是flush。
在更新之前,当内存数据⻚跟磁盘数据⻚内容不⼀致的时候,我们称这个内存⻚为“脏⻚”。
内存数据写⼊到磁盘后,内存和磁盘上的数据⻚的内容就⼀致了,称为“⼲净⻚“。
那什么时候会flush呢?
- InnoDB的redo log写满了,这时候系统会停⽌所有更新操作,把checkpoint往前推进,redo log留
出空间可以继续写。 - 系统内存不⾜,当需要新的内存⻚,⽽内存不够⽤的时候,就要淘汰⼀些数据⻚,空出内存给别的
数据⻚使⽤。如果淘汰的是“脏⻚”,就要先将脏⻚写到磁盘。
你⼀定会说,这时候难道不能直接把内存淘汰掉,下次需要请求的时候,从磁盘读⼊数据⻚,
然后拿redo log出来应⽤不就⾏了?
这⾥其实是从性能考虑的,如果刷脏⻚⼀定会写盘,就保证了每个数据⻚有两种状态:
⼀种是内存⾥存在,内存⾥就肯定是正确的结果,直接返回;
另⼀种是内存⾥没有数据,就可以肯定数据⽂件上是正确的结果,读⼊内存后返回。 这样的效率最
⾼。 - MySQL认为系统“空闲”的时候,只要有机会就刷⼀点“脏⻚”。
-
MySQL正常关闭,这时候,MySQL会把内存的脏⻚都flush到磁盘上,这样下次MySQL启动的时
候,就可以直接从磁盘上读数据,启动速度会很快
image.png
那我们怎么做才能把握flush的时机呢?
Innodb刷脏⻚控制策略,我们每个电脑主机的io能⼒是不⼀样的,你要正确地告诉InnoDB所在主机的IO
能⼒,这样InnoDB才能知道需要全⼒刷脏⻚的时候,可以刷多快。
这就要⽤到innodb_io_capacity这个参数了,它会告诉InnoDB你的磁盘能⼒,这个值建议设置成磁盘的
IOPS,磁盘的IOPS可以通过fio这个⼯具来测试。
正确地设置innodb_io_capacity参数,可以有效的解决这个问题。
这中间有个有意思的点,刷脏⻚的时候,旁边如果也是脏⻚,会⼀起刷掉的,并且如果周围还有脏⻚,
这个连带责任制会⼀直蔓延,这种情况其实在机械硬盘时代⽐较好,⼀次IO就解决了所有问题
但是现在都是固态硬盘了,innodb_flush_neighbors=0这个参数可以不产⽣连带制,在MySQL 8.0中,
innodb_flush_neighbors参数的默认值已经是0了
参考:《MySQL实战》、《⾼性能MySQL》、《丁奇MySQL47讲》
网友评论