Mysql - 脏页
1 . 脏页(内存页)
当内存数据页跟磁盘数据页内容不一致的时候,我们称这个内存页为“脏页”。内存数据写入到磁盘后,内存和磁盘上的数据页的内容就一致了,称为“干净页”。
不论是脏页还是干净页,都在内存中。
平时很快的更新操作,都是在写内存和日志。
一条 SQL 语句,正常执行的时候特别快,但是有时也不知道怎么回事,它就会变得特别慢。
那这时候可能就是在刷脏页到磁盘中了~ flush
2 . 什么时候会引起flush?
(1) InnoDB的redo log写满了。这时候系统会停止所有的更新操作,然后让日志可以继续写。
把这部分数据日志都flush到磁盘上面。
(2) 也可能是系统内存不足,需要新的内存页,那么就淘汰一些内存页,空出来的给别的数据页使用。
先把脏页写到磁盘。
PS:使用内存是为了效率更好,
因为如果内存存在数据页,那么数据就一定正确,直接返回;
如果内存没有数据,才需要去磁盘中取,读入到内存,返回;
(3) MySQL 认为系统“空闲”的时候,反正闲着也是闲着hh
反正有机会就刷点数据
(4)MySQL 正常关闭。这时候,MySQL 会把内存的脏页都 flush 到磁盘上,这样下次 MySQL 启动的时候,就可以直接从磁盘上读数据,启动速度会很快。
3 . 影响
3.1 如果是redo log写满了
尽量避免的。因为出现这种情况的时候,整个系统就不能再接受更新了,所有的更新都必须堵住。更新数为 0。
3.2 内存不够用了
常态,很正常。
3.3 buffer pool
因为innodb用的是buffer pool 管理内存,缓冲池中的内存页有三种状态:第一种是还没有使用的;第二种是使用了并且是干净页;第三种是使用了并且是脏页。
Innodb 的内存策略是尽量使用内存。
4 . Innodb 刷脏页的控制策略
我觉得知道一下就好,这个脏页刷的快不快跟磁盘的能力有关。
可以通过innodb_io_capacity 这个参数设置磁盘能力。
InnoDB 的刷盘速度就是要参考这两个因素:一个是脏页比例,一个是 redo log 写盘速度。
平时要多关注脏页比例,不要让它经常接近 75%。
INNODB刷脏页,如果发现旁边也是脏页,那么会连带着一起刷掉。
所以可能会很慢,如果你的查询正好要先flush一个脏页的话。
在 InnoDB 中,innodb_flush_neighbors 参数就是用来控制这个行为的,值为 1 的时候会有上述的“连坐”机制,值为 0 时表示不找邻居,自己刷自己的。
找“邻居”这个优化在机械硬盘时代是很有意义的,可以减少很多随机 IO。机械硬盘的随机 IOPS 一般只有几百。
但是SSD 的IO很高,所以可以不用非要有刷写邻居的操作,可以加快响应。
在 MySQL 8.0 中,innodb_flush_neighbors 参数的默认值已经是 0 了。
5 . QA
- Q:怎么知道一个也是不是脏页?
内存中每个数据页头部有LSN,8字节,每次修改都会变大。
对比这个LSN跟checkpoint 的LSN,比checkpoint小的一定是干净页
也就是如果内存中比redolog的头部小,那么就是干净页
- Q:LSN?
Log sequence number: 当前系统最大的LSN号
每个数据页有LSN,重做日志有LSN,checkpoint有LSN。
占用8字节,LSN主要用于发生crash时对数据进行recovery,LSN是一个一直递增的整型数字,表示事务写入到日志的字节总量。
LSN不仅只存在于重做日志中,在每个数据页头部也会有对应的LSN号,该LSN记录当前页最后一次修改的LSN号,用于在recovery时对比重做日志LSN号决定是否对该页进行恢复数据。前面说的checkpoint也是有LSN号记录的,LSN号串联起一个事务开始到恢复的过程。
感谢:https://www.cnblogs.com/drizzle-xu/p/9713378.html
我感觉就是可以理解为是一个long类型的数字,可以根据这个来比较要不要刷写数据,以及是不是干净页面,在恢复数据要拿这个进行比较。
- Q:buffer pool?
原文:https://blog.csdn.net/qq_27347991/article/details/81052728
缓存区域,缓存数据和索引在内存中。
innodb使用了一些链表。
lru链表:用来存储内存中的缓存数据。
free链表:用来存放所有的空闲页,每次需要数据页存储数据时,就首先检测free中有没有空闲的页来分配。
flush链表:在内存中被修改但还没有刷新到磁盘的数据页列表,就是所谓的脏页列表,内存中的数据跟对应的磁盘上的数据不一致,属于该列表的页面同样存在于lru列表中,但反之未必。
- Q:刷写的答题过程?
buffer pool里维护着一个脏页列表,假设现在redo log 的 checkpoint 记录的 LSN 为 10,现在内存中的一干净页有修改,修改后该页的LSN为12,大于 checkpoint 的LSN,则在写redo log的同时该页也会被标记为脏页记录到脏页列表中,现在内存不足,该页需要被淘汰掉,该页会被刷到磁盘,磁盘中该页的LSN为12,该页也从脏页列表中移除,现在redo log 需要往前推进checkpoint,到LSN为12的这条log时,发现内存中的脏页列表里没有该页,且磁盘上该页的LSN也已经为12,则该页已刷脏,已为干净页,跳过。
将脏页flush到磁盘上是直接将脏页数据覆盖到对应磁盘上的数据
-
Q: 很多测试人员再做压力测试的时候写入慢也跟redolog有关?
出现刚开始 insert update 很快 一会 就出现很慢,并且延迟很大,大部分是因为redo log 设置太小 引起的 -
Q:如果系统性能差,为什么会慢?
因为脏页刷的很慢,堆积了之后,就会等待脏页刷完之后在进行更新和读取。
————————————————
版权声明:本文为CSDN博主「pmdream」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/pmdream/article/details/103668933