在之前我们说过酒店记账的故事,其中酒店掌柜记账的的黑板就类似我们的redo log,而掌柜的记账本就是数据文件,掌柜的记忆就是内存。
而掌柜的要把黑板的数据记录在账本上,就类似我们把内存的数据写入磁盘的过程,这个过程就叫做flush.在flush之前,掌柜的账本和掌柜的记忆其实是不一致的,因为有部分数据还在黑板上,
往往当内存的数据和磁盘的数据不一致的时候,我们称这个内存也就是脏页,内存数据写入磁盘后,数据保持一致,我们称之为干净页。
在日常工作中,我们执行sql的非常快,那是因为,我们仅仅在写内存和日志,但是偶尔会发数据库抖了一下,sql执行很慢,这个时候可能就是在刷脏页.
那什么时候会发生flush呢
上面的四种场景,3,4两种场景对性能没有影响,主要分析一下1,2两种场景。
第一种redolog写满了,要刷新脏页,这个情况系统要尽量避免,因为这样会导致系统无法接受更新,
第二种情况,内存不够用了,就会把脏页写到磁盘,这种其实是常态,innoDB管理内存,缓冲中的内存也有三种状态
innoDB要尽量使用内存,因此对于一个长时间运行的库来说,未被使用的页面很少.而当内存不够的时候,就要向缓冲池申请数据页,这个时候只能把最久不使用的数据页从内存中淘汰掉,如果是干净页,就直接释放复用,如果是脏页,就必须先刷新到磁盘,变成干净页之后复用。
尽管刷脏页的是常态但是出现下面两种情况,都会影响性能
所以innodb需要有控制脏页比例机制,来尽量避免上面的两种情况,
Innodb刷脏页的控制策略
首先,你要正确的告诉innoDB所在主机的IO能力,这样innodb才能知道需要全力刷脏页的速度,能有多快。我们可以设置innodb_io_capacity这个参数,他会告诉你磁盘的能力,这个值建议你设置成磁盘的IOPS,磁盘的IOPS可以通过下面工具测试,如下面语句
fio -filename=$filename -direct=1 -iodepth 1 -thread -rw=randrw -ioengine=psync -bs=16k -size=500M -numjobs=10 -runtime=10 -group_reporting -name=mytest
如果不能正确的设置这个参数,导致的性能问题也是比比皆是.
虽然我们说的是全力刷脏页,但是实际上我们并不能这样去做,后台还有其他的请求,因此我们要看看如何控制引擎按照全力的百分比刷脏页
控制刷脏页的速度有哪些因素呢
刷盘的速度一般有两方面,一个是脏页比例,一个是redo log写盘速度,
现在我们知道,innodb会在后台刷脏页,而刷脏页的过程无论将内存写入磁盘,还是刷脏页占用IO的资源并可能影响到了你的更新语句,都有可能让业务员感到mysq抖一下的原因。
我们要避免避免inndb_io_capacity的值,并在平常要多关心脏页比例,不要让他接近75%。脏页的比例=innodb_buffer_poll_pages_dirty/innodb_buffer_pool_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;
一旦一个查询请求需要执行的过程需要刷脏页的时候,就可能非常慢,而mysql还有另外一个机制,当一个脏页要被刷到磁盘的时候,发现旁边的数据页也是脏页,也会把这个脏页一块刷到磁盘,这种机制可能会导致,很多脏页一起被刷新到磁盘,从而影响性能,对应的控制参数是innodb_flush_neighbors就是控制这个机制的,0是关闭,只会自己刷自己,1打开,会导致上面那样影响性能,
但是对于机械硬盘这样做是很有意义的,可以减少很多随机io,机械硬盘的随机IOPS一般只有几百,相同的逻辑操作减少io磁盘,提高系统性能,
而如果是SSD这类IOPS比较高的设备的话,我们一般建议把innodb_flush_neighbors设置成0.仅仅刷自己,进而更快的刷脏页的操作,减少sql语句响应时间,而mysql8.0中就已经把0设置成了默认值.
欢迎持续关注,如果对你有一丝丝帮助,麻烦点个关注,也欢迎点赞转发