首页 > 其他分享 >InnoDB引擎之flush脏页

InnoDB引擎之flush脏页

时间:2023-04-10 14:36:26浏览次数:47  
标签:Buffer 链表 InnoDB LRU flush 磁盘 脏页

利用 WAL 技术,数据库将随机写转换成了顺序写,大大提升了数据库的性能,由此也带来了内存脏页的问题。

 脏页会被后台线程自动 flush,也会由于数据页淘汰而触发 flush,而刷脏页的过程由于会占用资源,可能会让你的更新和查询语句的响应时间长一些。

 

一、flush 脏页

当内存数据页跟磁盘数据页内容不一致的时候,我们成这个内存页为“脏页”;内存数据写入磁盘后,内存和磁盘上的数据页内容就一致了,称为“干净页”。

 

InnoDB引擎以页作为磁盘和内存之间交互的基本单位,数据库 I/O 操作的最小单位是页。也就是说,在数据库中,不论读一行,还是读多行,都是将这些行所在的页进行加载。

 

 

 

记录是按照行来存储的,但是数据库的读取并不以行为单位,否则一次读取(也就是一次 I/O 操作)只能处理一行数据,效率会非常低。 

Buffer Pool 中存的就是一页一页的数据,当我们要查询的数据不在 Buffer Pool 中时,InnoDB 会将记录所在的页整个加载到 Buffer Pool 中去。

同样的,将 Buffer Pool 中的脏页刷入磁盘时,也是按照页为单位刷入磁盘的。

  

1、Free List

你从磁盘中读取一个数据页,会先从Free List中找出一个空闲缓存页的描述信息,然后将你读出的数据页中加载进缓存页中。同时将缓存页的描述信息从Free List中剔除,此外该描述信息块还会被维护进LRU链表中。

数据页被加载进Buffer Pool后你就可以对其进行变更操作了。

 

3、Flush List

如果我们修改了Buffer Pool中某个缓冲页的数据,那么它就与磁盘上的页不一致了,这样的缓冲页也被称之为脏页(dirty page)。

为了性能问题,我们每次修改缓冲页后,并不着急立刻把修改刷新到磁盘上,而是在未来的某个时间点进行刷新操作。 

如果有了修复发生,不是立刻刷新,那之后再刷新的时,我们怎么知道Buffer Pool中哪些页是脏页,哪些页从来没有被修改过呢?

 

创建一个存储脏页的 Flush list,凡是被修改过的缓冲页对应的控制块都会作为节点加入到这个链表中。

4、LRU List

除了以上,Buffer Pool还有另外一种LRU List,整体结构如下:

 

 

 

 

在BufferPool中,内存管理如下:

  • 需要找 free 空闲数据块:free list
  • 需要找冷热访问的数据块:lru list
  • 需要知道哪些数据块是脏的:flush list

 

 

二、刷新方式有哪几种

1、从flush链表中刷新一部分页面到磁盘

 

后台线程会根据当时系统的繁忙程度确定刷新速率,定时从flush链表中刷新一部分页面到磁盘,即:BUF_FLUSH_LIST

 有时后台线程刷新脏页的进度比较慢,导致用户准备加载一个磁盘页到Buffer Pool中时没有可用的缓冲页。此时,就会尝试查看LRU链表尾部,看是否存在可以直接释放掉的未修改缓冲页。

如果没有,则不得不将LRU链表尾部的一个脏页同步刷新到磁盘(与磁盘交互是很慢的,这会降低处理用户请求的速度),即:BUF_FLUSH_SINGLE_PAGE

 

2、从LRU链表的冷数据中刷新一部分页面到磁盘,即:BUF_FLUSH_LRU

 

后台线程会定时从LRU链表的尾部开始扫描一些页面,扫描的页面数量可以通过系统变量innodb_lru_scan_depth来指定,如果在LRU链表中发现脏页,则把它们刷新到磁盘。

控制块里会存储该缓冲页是否被修改的信息,所以在扫描LRU链表时,可以很轻松地获取到某个缓冲页是否是脏页的信息。

 

三、flush性能问题

flush脏页虽然是常态,但是出现以下这两种情况,都是会明显影响性能的:

  1. 一个查询要淘汰的脏页个数太多,会导致查询的响应时间明显变长;
  2. 日志写满,更新全部堵住,写性能跌为 0,这种情况对敏感业务来说,是不能接受的。

 

InnoDB 会在后台刷脏页,而刷脏页的过程是要将内存页写入磁盘。所以,无论是你的查询语句在需要内存的时候可能要求淘汰一个脏页,还是由于刷脏页的逻辑会占用 IO 资源并可能影响到了你的更新语句,都可能是造成你从业务端感知到 MySQL“抖”了一下的原因。

 

要尽量避免这种情况,你就要合理地设置 innodb_io_capacity 的值,并且平时要多关注脏页比例,不要让它经常接近 75%。 

一旦一个查询请求需要在执行过程中先 flush 掉一个脏页时,这个查询就可能要比平时慢了。

而 MySQL 中的一个机制,可能让你的查询会更慢:在准备刷一个脏页的时候,如果这个数据页旁边的数据页刚好是脏页,就会把这个“邻居”也带着一起刷掉;而且这个把“邻居”拖下水的逻辑还可以继续蔓延,也就是对于每个邻居数据页,如果跟它相邻的数据页也还是脏页的话,也会被放到一起刷。

 

在 InnoDB 中,innodb_flush_neighbors 参数就是用来控制这个行为的,值为 1 的时候会有上述的“连坐”机制,值为 0 时表示不找邻居,自己刷自己的。

找“邻居”这个优化在机械硬盘时代是很有意义的,可以减少很多随机 IO。机械硬盘的随机 IOPS 一般只有几百,相同的逻辑操作减少随机 IO 就意味着系统性能的大幅度提升。

而如果使用的是 SSD 这类 IOPS 比较高的设备的话,建议你把 innodb_flush_neighbors 的值设置成 0。因为这时候 IOPS 往往不是瓶颈,而“只刷自己”,就能更快地执行完必要的刷脏页操作,减少 SQL 语句响应时间。

在 MySQL 8.0 中,innodb_flush_neighbors 参数的默认值已经是 0 了。

 

参考资料:

https://hackmysql.com/post/book-6/

《MySQL实战45讲》

 

 

 

标签:Buffer,链表,InnoDB,LRU,flush,磁盘,脏页
From: https://www.cnblogs.com/binyue/p/17302812.html

相关文章

  • 第7章_InnoDB数据存储结构
    1.数据库的存储结构:页索引结构给我们提供了高效的索引方式,不过索引信息以及数据记录都是保存在文件上的,确切说是存储在页结构中。另一方面,索引是在存储引擎中实现的,MysQL服务器上的存储引擎负责对表中数据的读取和写入工作。不同存储引擎中存放的格式一般是不同的,甚至有的存储引......
  • MySQL Replication--Failed to flush master info 问题
    问题描述MySQL复制不定期出现问题,报错为:Failedtoflushmasterinfo,但具体原因尚未定位到。涉及代码查看MySQL5.7.34版本的代码:intflush_master_info(Master_info*mi,boolforce){DBUG_ENTER("flush_master_info");assert(mi!=NULL&&mi->rli!=NULL);/*......
  • vue3 watch 监听 flush post 作用?
    副作用刷新时机Vue的响应性系统会缓存副作用函数,并异步地刷新它们,这样可以避免同一个“tick”中多个状态改变导致的不必要的重复调用。同一个“tick”的意思是,Vue的内部机制会以最科学的计算规则将视图刷新请求合并成一个一个的"tick",每个“tick”刷新一次视图,比如a=1;b=2;只会......
  • InnoDB 事务加锁分析
    vivo互联网技术微信公众号 作者:何志创一般大家对数据库事务的了解可能停留在事务的ACID特性以及事务4种不同的隔离级别层面上,而对于事务4种不同隔离级别如何实现了解相对较少。本文以MySQL数据库 InnoDB 引擎为例,为大家分析 InnoDB数据库引擎对默认的隔离级别可重复读(RR......
  • MySQL(九)InnoDB行格式
    InnoDB行格式查看默认行格式:select@@innodb_default_row_format;查看数据库表使用的行格式mysql>useatguigudb;ReadingtableinformationforcompletionoftableandcolumnnamesYoucanturnoffthisfeaturetogetaquickerstartupwith-ADatabasechanged......
  • MySQL(九)InnoDB数据结构
    InnoDB数据结构1数据库的存储结构:页​ 索引信息和数据记录都是保存在文件上的,确切来说是保存在页结构中;另一方面,索引是在存储引擎上实现的,MySQL服务器上的存储引擎负责对表中数据的读取和写入工作。不同的存储引擎的存放格式是不同的,比如Memory甚至不使用磁盘进行存储数据。......
  • 68.innodb之关键特性(异步IO)
    mysql支持异步io,为了提高磁盘操作性能,当前的数据库系统都采用异步IO(AsynchronousIO,AIO)的方式来处理磁盘操作异步IO相较于同步IO而言的是,当它每扫描一个页之后不需要等待其完成就可以再进行扫描下一次的扫描,另外一个优势是可以进行IOmerge操作,也就是可以将多个IO合并成一个IO......
  • Turn your Session into FlushMode.COMMIT/AUTO or remove 'readOnly' marker from tr
    Writeoperationsarenotallowedinread-onlymode(FlushMode.NEVER/MANUAL):TurnyourSessionintoFlushMode.COMMIT/AUorg.springframework.dao.InvalidDataAccess......
  • 解决 Turn your Session into FlushMode.COMMIT/AUTO or remove 'readOnly' marker
    org.springframework.dao.InvalidDataAccessApiUsageException:Writeoperationsarenotallowedinread-onlymode(FlushMode.NEVER/MANUAL):TurnyourSessioninto......
  • [React] Flushing state updates synchronously with flushSync
    InReact,everyupdateissplitintwophases:During render, Reactcallsyourcomponentstofigureoutwhatshouldbeonthescreen.During commit, React......