当内存数据页跟磁盘数据页内容不一致的时候,称这个内存页为“脏页”。下面模拟一个店家记录赊账的过程,本来赊账10块钱,现在变成19块钱。
有几种需要flush的场景:
- Redo log写满,这个时候系统就会停止所有的更新操作,把checkpoint往前推进,redo log流出空间继续写:
例如上图的把cp移动到cp’,那么就要对两点之间的脏页都刷到磁盘上。
- 内存不足,这时候就要淘汰一些数据页,如果淘汰的是脏页,那么久要刷盘。
- 系统空闲时。
- Mysql正常关闭。
我们看前两种场景对性能的影响
- Redo log 写满,这种情况是要尽量避免的,因为出现的时候,系统就不接受更新了。
- 内存不足,那么这个时候,内存里面就有三种情况:还没使用、使用了但未更新、脏页。这个时候,只能把最久不适用的数据页从内存中淘汰掉。
那么InnoDB就需要控制脏页的比例,避免频繁刷脏页的场景。
innodb_io_capacity这个参数会告诉InnoDB你的磁盘能力,一般设置成磁盘的IOPS。InnoDB的刷盘速度考虑主要有脏页比例和redo log写盘速度。InnoDB会根据这两个因素单独算出两个数字。
innodb_max_dirty_pages_pct是脏页的比例上限,默认是75%,InnoDB会根据当前的脏页比例,脏页比例是通过Innodb_buffer_pool_pages_dirty/Innodb_buffer_pool_pages_total得到的,算出一个范围在0到100之间的数字,如下:
在算出,InnoDB每次写入的日之间都有一个序号,写入的序号跟checkpoint对应的序号之间的差值,假设是N,根据这个N算出一个范围在0到100之间的数字,F2(N),N越大,F2(N)越大。算出来再取二者最大值即为R,根据innode_io_capacity乘以R%控制刷脏页的速度。
InnoDB还有一个机制,就是在刷盘的时候,如果数据页的邻居也是脏页,那么也会一起刷,为了不影响性能,,innodb_flush_neighbors 参数就是用来控制这个行为,设置为了0(默认也是0),就是只刷自己。