如何解决mysql警告:" InnoDB:page_cleaner:1000ms意图循环花了XXX毫秒。设置可能不是最佳的"?

时间:2016-12-14 04:20:19

标签: mysql mysql-5.6 mysql-5.7

我运行了一个mysql import mysql dummyctrad<服务器上的dumpfile.sql,它需要很长时间才能完成。转储文件大约是5G。服务器是Centos 6,内存= 16G和8核处理器,mysql v 5.7 x64 -

这些正常的消息/状态"等待表刷新"和消息InnoDB: page_cleaner: 1000ms intended loop took 4013ms. The settings might not be optimal

mysql日志内容

2016-12-13T10:51:39.909382Z 0 [Note] InnoDB: page_cleaner: 1000ms intended loop took 4013ms. The settings might not be optimal. (flushed=1438 and evicted=0, during the time.)
2016-12-13T10:53:01.170388Z 0 [Note] InnoDB: page_cleaner: 1000ms intended loop took 4055ms. The settings might not be optimal. (flushed=1412 and evicted=0, during the time.)
2016-12-13T11:07:11.728812Z 0 [Note] InnoDB: page_cleaner: 1000ms intended loop took 4008ms. The settings might not be optimal. (flushed=1414 and evicted=0, during the time.)
2016-12-13T11:39:54.257618Z 3274915 [Note] Aborted connection 3274915 to db: 'dummyctrad' user: 'root' host: 'localhost' (Got an error writing communication packets)

PROCESSLIST:

mysql> show processlist \G;
*************************** 1. row ***************************
     Id: 3273081
   User: root
   Host: localhost
     db: dummyctrad
Command: Field List
   Time: 7580
  State: Waiting for table flush
   Info: 
*************************** 2. row ***************************
     Id: 3274915
   User: root
   Host: localhost
     db: dummyctrad
Command: Query
   Time: 2
  State: update
   Info: INSERT INTO `radacct` VALUES (351318325,'kxid ge:7186','abcxyz5976c','user100
*************************** 3. row ***************************
     Id: 3291591
   User: root
   Host: localhost
     db: NULL
Command: Query
   Time: 0
  State: starting
   Info: show processlist
*************************** 4. row ***************************
     Id: 3291657
   User: remoteuser
   Host: portal.example.com:32800
     db: ctradius
Command: Sleep
   Time: 2
  State: 
   Info: NULL
4 rows in set (0.00 sec)

更新-1

mysqlforuminnodb_lru_scan_depth

将innodb_lru_scan_depth值更改为256改进了插入查询执行时间+日志中没有警告消息,默认为innodb_lru_scan_depth = 1024;

SET GLOBAL innodb_lru_scan_depth=256;

3 个答案:

答案 0 :(得分:56)

  

InnoDB:page_cleaner:1000ms意图循环需要4013ms。设置可能不是最佳的。 (刷新= 1438,并且在此期间被驱逐= 0。)

问题是MySQL实例的典型问题,您对数据库的更改率很高。通过运行5GB导入,您可以快速创建脏页。在创建脏页时,页面清理程序线程负责将脏页从内存复制到磁盘。

在您的情况下,我假设您不会一直进行5GB的导入。所以这是一个异常高的数据加载速率,这是暂时的。您可以忽略这些警告,因为InnoDB会逐渐赶上。

以下是导致此警告的内部细节的详细说明。

每秒一次,页面清理程序扫描缓冲池以查找脏页以从缓冲池刷新到磁盘。您看到的警告显示它有大量要刷新的脏页,将一批它们刷新到磁盘需要4秒以上,而它应该在1秒内完成该工作。换句话说,它咬得比咬得多。

您通过将innodb_lru_scan_depth从1024减少到256来调整此值。这减少了页面清除程序线程在每秒一次的周期内搜索脏页的缓冲池的距离。你要求它采取较小的咬伤。

请注意,如果您有许多缓冲池实例,则会导致刷新以执行更多工作。它咬掉了每个缓冲池实例的innodb_lru_scan_depth工作量。因此,您可能会在不降低扫描深度的情况下通过增加缓冲池的数量而无意中造成此瓶颈。

innodb_lru_scan_depth的文档说“小于默认值的设置通常适用于大多数工作负载。”听起来他们默认为这个选项提供了一个太高的值。

您可以使用innodb_io_capacityinnodb_io_capacity_max选项对背景刷新使用的IOPS进行限制。第一个选项是InnoDB将要求的I / O吞吐量的软限制。但这个限制是灵活的;如果刷新落后于新脏页面创建的速度,InnoDB将动态增加超出此限制的刷新率。第二个选项定义了一个更严格的限制,即InnoDB可以提高冲洗率。

如果刷新率可以跟上创建新脏页的平均速度,那么你就可以了。但是如果你一直创建脏页的速度比刷新的速度快,那么最终你的缓冲池将填满脏页,直到脏页超过缓冲池的innodb_max_dirty_page_pct。此时,刷新率将自动增加,并可能再次导致page_cleaner发送警告。

另一个解决方案是将MySQL放在具有更快磁盘的服务器上。您需要一个可以处理页面刷新所需吞吐量的I / O系统。

如果您在平均流量下始终看到此警告,则可能是在此MySQL服务器上尝试执行过多的写入查询。可能是时候向外扩展,并将写入分割为多个MySQL实例,每个实例都有自己的磁盘系统。

阅读有关页面清洁工具的更多信息:

答案 1 :(得分:9)

瓶颈是将数据保存到HDD。无论你有什么硬盘驱动器:SSD,普通硬盘,NVMe等。

请注意,此解决方案主要适用于InnoDB

我遇到了同样的问题,我已经应用了很少的解决方案。

第一:检查错误

atop -d会显示磁盘使用情况。如果磁盘“忙”,那么尝试停止对数据库的所有查询(但不要停止mysql服务器服务!)

要监控您拥有的查询数量,请使用mytop,innotop或同等数据。

如果您有0个查询,但磁盘使用率仍然是几秒/几分钟的100%,那么这意味着,mysql服务器正在尝试刷新脏页面/如前所述进行一些清理(很棒的帖子) Bill Karwin)。

那么你可以尝试应用这样的解决方案:

第二名:硬件优化

如果您的阵列不在RAID 1 + 0中,请考虑使用此类解决方案加快保存数据的速度。尝试通过写入数据来扩展HDD cotroller的可能性。尝试使用SSD或更快的HDD。应用这种灵魂取决于你的硬件和预算可能性,可能会有所不同。

3nd:软件调整

如果harware cotroller工作正常,但你想扩展保存数据的速度,你可以在mysql配置文件中设置:

3.1。

innodb_flush_log_at_trx_commit = 2 - >如果你/使用innodb表 它的形成方式最好,每个文件有一个表: innodb_file_per_table = 1

3.2。

继续使用InnoDB: innodb_flush_method = O_DIRECT innodb_doublewrite = 0 innodb_support_xa = 0 innodb_checksums = 0

以上行通常会减少需要保存在HDD中的数据量,因此性能更高。

3.3

general_log = 0 slow_query_log = 0

上面的行禁用保存日志,当然这是另外一些要保存在HDD上的数据

3.4 再次检查发生了什么,例如 tail -f /var/log/mysql/error.log

第4次:一般性说明

一般说明: 这是在MySQL 5.6和5.7.22下测试的 操作系统:Debian 9 RAID:1 + 0 SSD驱动器 数据库:InnoDB表 innodb_buffer_pool_size = 120G innodb_buffer_pool_instances = 8 innodb_read_io_threads = 64 innodb_write_io_threads = 64 服务器中的RAM总量:200GB

执行此操作后,您可能会观察到更高的CPU使用率;这是正常的,因为写数据更快,所以CPU会更加努力。

如果您使用my.cnf这样做,请不要忘记重启MySQL服务器。

第五名:补充

Beeing好奇我做了这个怪癖 SET GLOBAL innodb_lru_scan_depth=256; 如上所述。

使用大桌子我发现表现没有任何变化。

经过上述修正后,我没有发现警告,但整个系统的运行速度要快得多。 以上所有内容只是一个实验,但我测量了结果,它对我有所帮助,所以希望它对其他人有用。

答案 2 :(得分:1)

通常,这仅表示文件系统性能不佳-这是不相关问题的征兆。就我而言,我花了一个小时研究此问题,分析了我的系统日志,并且当我决定检查基于云的托管时,已经接近调整MySQL配置的地步了。事实证明,存在“来自邻居的滥用I / O尖峰”。在引起他们注意之后,我的主人迅速解决了这个问题。

我的建议是了解基线/预期的文件系统性能,停止MySQL,并测量文件系统性能,以确定是否还有与MySQL无关的其他基本问题。