在InnoDB MySQL中刷新到磁盘之前,脏的数据库页面通常在内存中保留多长时间?

时间:2018-12-21 14:01:42

标签: mysql innodb computer-forensics

我指的是数据库页面:

https://dev.mysql.com/doc/internals/en/innodb-page-structure.html

现在,当我们对它发出查询时,这些页面将被加载到内存中,并且仅在其中进行更改并被标记为脏

我不确定这是否取决于操作系统或数据库,但是我的问题是这些页面通常在内存中停留多长时间?

让我们说我们有一个用于高负载Web服务器的数据库,它的流量很大,缓冲区大小大约为1gb或类似的东西(不确定通常有多少数据库服务器),现在这1gb中有多少是脏页?

并且如果没有备用电源就断电了,那么对这些脏页的所有更改都会丢失正确吗? (基本上,我想知道是否发生断电,如果没有备用电源,并且发生大量插入和查询,那么丢失的内存中脏数据的估计百分比是多少?)

例如这些脏页是否有可能在繁忙的服务器上停留超过12或24小时?

编辑:脏页是指该页已在内存中修改,例如其中的一行已更新或删除

1 个答案:

答案 0 :(得分:3)

  

这些页面通常在内存中停留多长时间?

是可变的。 InnoDB有一个后台线程将脏页刷新到磁盘。它会刷新少量的页面,然后在1秒后再次刷新。

因此,如果您在短时间内进行大量更新,则会使许多页面变脏。然后,冲洗线程将逐渐将它们冲洗到磁盘上。这个想法是,这有助于随着时间的推移而扩展工作,因此突然的更新高峰不会使您的磁盘不堪重负。

但是,这意味着“这些页面在内存中脏了多久”可以有很大的不同。我认为通常情况下,几分钟后即可完成。

不同版本的MySQL以不同的方式刷新。几年前,主后台线程每1秒刷新固定数量的页面。然后他们提出了自适应冲洗功能,因此如果它检测到您进行了很多更改,它将自动提高冲洗速率。然后,他们提出了一个称为页面清洁器的专用线程。我认为甚至可以将MySQL配置为运行多个页面清理程序线程,但这对于大多数应用程序不是必需的。

您可能也对我对这些过去问题的回答感兴趣:

  

让我们说...缓冲区大小约为1gb之类的(不确定数据库服务器通常有多少)

它确实有所不同,并取决于应用程序。开箱即用的默认innodb缓冲池大小为128MB,但这对于大多数应用程序来说太小了,除非它是一个测试实例。

在我的公司,我们尝试将缓冲池保持在磁盘上至少10%的数据大小。一些应用程序需要更多。我们最常用的大小是24GB,但是最小的大小是1GB,最大的大小是200GB。我们管理着4,000多个生产MySQL实例。

  

这1GB中有多少是脏页?

所有这些,从理论上讲。 MySQL有一个名为innodb_max_dirty_pages_pct的配置变量,如果您有太多的话,您可能会认为它会阻塞任何其他脏页。但事实并非如此。即使缓冲池比该变量脏(百分比),您仍然可以修改更多页面。

该变量的真正作用是,如果缓冲池超过脏页的百分比,则刷新脏页的速率会增加(IIRC,它将每个周期刷新的页数加倍),直到数量下降再次低于该百分比阈值。

  

如果没有备用电源而断电,那么对这些脏页的所有更改都会丢失正确吗?

是的,但是您不会丢失更改,因为可以从InnoDB重做日志中重建它们-您可能已经在数据目录中看到了这两个文件iblogfile_0iblogfile_1。提交期间,任何创建脏页的事务都必须记录在重做日志中。

如果您断电(或以其他方式重新启动mysqld进程),InnoDB要做的第一件事是扫描重做日志以检查记录的每个更改在崩溃前是否已刷新,否则,请加载原始页面,然后重新应用日志中的更改以再次创建脏页面。这就是InnoDB所谓的崩溃恢复。

您可以观看这种情况。在kill -9 mysqld进程期间,在MySQL Server的测试实例上尾标错误日志。 mysqld_safe将重新启动mysqld进程,这将在执行崩溃恢复时向错误日志中注入大量信息。

如果只有少量脏页要恢复,这将非常快,也许只有几秒钟。如果缓冲池很大,并且有很多脏页,则需要更长的时间。在崩溃恢复完成之前,MySQL服务器尚未完全启动,并且无法建立新的客户端连接。在观察崩溃恢复的进度时,这已经引起了许多MySQL DBA的焦虑。无法预测崩溃后需要多长时间。

由于恢复崩溃需要重做日志,因此,如果重做日志已满,MySQL 必须刷新一些脏页。它不会清除脏页,也无法从重做日志中恢复它们。如果发生这种情况,您实际上会看到InnoDB暂停了写操作,直到它可以对最旧的脏页执行“紧急刷新”。对于MySQL来说,这曾经是一个问题,但是随着自适应刷新和页面清理器的改进,它可以更好地跟上更改的步伐。您必须拥有非常大量的写入操作,并且重做日志的大小要小,以便在InnoDB进行同步刷新时遇到硬停止。

这是一个有关冲洗的好博客:https://www.percona.com/blog/2011/04/04/innodb-flushing-theory-and-solutions/

P.S .:对于MyISAM的强制性要求,我将指出MyISAM没有重做日志,没有崩溃恢复,并且在写入其数据文件期间依赖于主机OS文件缓冲区。如果主机电源出现故障,而文件缓冲区中有未决的写操作尚未写入磁盘,则您将丢失它们。 MyISAM对ACID的耐用性属性没有任何真正的支持。


发表评论:

在重做日志回收时,页面可能已被刷新。也就是说,如果您有2个48MB的重做日志文件(默认大小),并且向其写入了足够的事务以完全循环通过它并从头开始,则在此期间缓冲池中变脏的任何页面都需要被冲洗。如果重做日志中的相应事务被新事务覆盖,则页面不能在BP中保持脏状态。

据我了解,脏页几乎不可能在不刷新12-24小时的情况下保持在缓冲池中。

可能的例外,我只是在猜测,是给定页面在刷新之前一次又一次地更新。因此,它长期以来一直是最近的脏页。同样,我不确定重做日志回收时是否能克服刷新页面的需要。

无论如何,我认为这种可能性很小。

此外,我也不知道您所说的法医是什么意思。没有直接方法可以从缓冲池检查页面版本。要从InnoDB获取有关最近更改的信息,您需要检查undo段以查找页面的先前版本,并将它们与重做日志条目相关联。脏页及其以前的版本都可以在缓冲池中或磁盘上。没有命令或API或任何数据结构可以进行任何这种关联。因此,您需要手动转储磁盘映像和内存映像,并手动跟踪指针。

跟踪数据更改的一种更简单的方法是检查二进制日志中的更改流。这独立于InnoDB。