平时的工作中, 一条SQL语句, 正常执行的时候特别快, 但是有时也不知道怎么回事, 它就会变得特别慢, 并且这样的场景很难复现, 它不只随机, 而且持续时间还很短。
就像mysql抖了一下。这种情况可能的原因有哪些呢?
1、redo log 满了,需要flush到磁盘中,checkpoint后移。此时系统所有更新操作都会阻塞住。
一般来说,我们的redo log是由4个文件组成的,每个文件写满会自动写到下一个文件,最后一个文件写满,会自动跳回第一个文件。mysql会记录当前写入文件的位置,记为write pos,而同时也需要将redo log写盘,此时flush的位置记为checkpoint.如图。
当write pos 追上checkpoint 的时候,我们无法再往redo log 中写入数据,需要先flush,将checkpoint往后移动,才能继续写入数据。redo log 无法写入数据,那么所有的修改数据操作都不可执行。所以mysql会抖一下。
2、内存满了,必须要淘汰部分数据页。如果数据页是脏页,需要flush变成干净页才能使用。
这个很好理解,mysql所有的操作都是在内存中操作的,当内存页都已经被使用,必须先将部分内存页flush到磁盘中释放出来,才可以继续下面的操作。
3、内存脏页flush联动。
如果刷当前脏页后,发现相邻的页也是脏页,那么就会把相邻的内存页也刷掉,且会一直联动直到相邻页不是脏页。可以配置 innodb_flush_neighbors=0,表示自己刷自己,不刷相邻脏页。这个设置在磁盘是SSD下是很有效的。