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

标签 mysql innodb computer-forensics

我所说的数据库页面是:

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

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

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

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

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

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

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

最佳答案

how long do these pages usually stay dirty in memory?



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

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

但这意味着“这些页面在内存中脏了多久”可能会有很大不同。我认为在典型情况下,几分钟即可完成。

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

您可能也对我对这些过去问题的回答感兴趣:
  • How to calculate amount of work performed by the page cleaner thread each second?
  • How to solve mysql warning: "InnoDB: page_cleaner: 1000ms intended loop took XXX ms. The settings might not be optimal "?

  • Lets say ... the buffer size is like 1gb or something(not sure how much database servers usually have)



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

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

    how much of these 1gb could be dirty pages?



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

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

    if the power is lost with no backup power, then all of the changes to these dirty pages get lost correct?



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

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

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

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

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

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

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

    发表您的评论:

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

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

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

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

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

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

    关于mysql - 在InnoDB MySQL中刷新到磁盘之前,脏的数据库页面通常在内存中保留多长时间?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53886068/

    相关文章:

    MySQL Multi DELETE 如果与外键存在关系

    computer-forensics - 封装取证.dd

    mysql - Postgresql 错误 (heroku) - 在 mysql 上本地工作

    php - mysql 查询与连接

    mysql - 选择更改其最后值的记录

    mysql - 如何使用 IN 运算符处理 MySQL Select 的结果

    php - 大型数据集 : mysql_unbuffered_query with innodb?

    mysql - 如何同步 MySQL 日志

    python - 是否可以使用正则表达式通过十六进制查找电子邮件地址

    opencv - 计算机视觉 : nudity detection solutions comparision (opencv based or custom code) & hash-lists & client side