如何解决 mysql 警告:“InnoDB:page_cleaner:1000ms 预期循环花费了 XXX 毫秒。设置可能不是最佳的”?
Posted
技术标签:
【中文标题】如何解决 mysql 警告:“InnoDB:page_cleaner:1000ms 预期循环花费了 XXX 毫秒。设置可能不是最佳的”?【英文标题】:How to solve mysql warning: "InnoDB: page_cleaner: 1000ms intended loop took XXX ms. The settings might not be optimal "? 【发布时间】:2017-04-29 07:43:31 【问题描述】:我在服务器上运行了一个 mysql import mysql dummyctrad
这些是正常的消息/状态“等待表刷新”和消息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)
进程列表:
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)
Update-1
mysqlforum,innodb_lru_scan_depth
将 innodb_lru_scan_depth 值更改为 256 提高了插入查询的执行时间 + 日志中没有警告消息,默认值为 innodb_lru_scan_depth=1024;
SET GLOBAL innodb_lru_scan_depth=256;
【问题讨论】:
真正的问题是什么?花费太长时间并不是我认为一次性过程的问题!您能否更具体一些,如果您看到任何错误?您是否有任何日志可能表明正在发生的事情?抱歉,只是没有足够的信息可供任何人提供帮助 真正的问题是什么?这更像是一份状态报告,而不是一个问题。 【参考方案1】:InnoDB: page_cleaner: 1000ms 预期循环耗时 4013ms。设置可能不是最佳的。 (在此期间,flushed=1438 和 evicted=0。)
此问题是 MySQL 实例的典型问题,您对数据库的更改率很高。通过运行 5GB 导入,您正在快速创建脏页。在创建脏页时,页面清理线程负责将脏页从内存复制到磁盘。
在您的情况下,我假设您不会一直进行 5GB 的导入。所以这是一个非常高的数据加载率,而且是暂时的。您可能可以忽略警告,因为 InnoDB 会逐渐赶上来。
以下是导致此警告的内部细节的详细说明。
页面清理器每秒扫描一次缓冲池中的脏页以从缓冲池刷新到磁盘。您看到的警告表明它有很多脏页要刷新,将一批脏页刷新到磁盘需要超过 4 秒,而它应该在 1 秒内完成这项工作。换句话说,它咬的比它咀嚼的还多。
您通过将innodb_lru_scan_depth
从 1024 减少到 256 对此进行了调整。这减少了页面清理器线程在其每秒一次的循环中搜索脏页到缓冲池的距离。你要求它吃小口。
请注意,如果您有许多缓冲池实例,则会导致刷新完成更多工作。它咬掉了每个缓冲池实例的innodb_lru_scan_depth
工作量。因此,您可能在不降低扫描深度的情况下增加缓冲池的数量,无意中造成了这个瓶颈。
innodb_lru_scan_depth
的文档说“小于默认值的设置通常适用于大多数工作负载。”听起来他们给这个选项默认的值太高了。
您可以使用innodb_io_capacity
和innodb_io_capacity_max
选项限制后台刷新使用的IOPS。第一个选项是对 InnoDB 请求的 I/O 吞吐量的软限制。但是这个限制是灵活的;如果刷新速度落后于新脏页创建的速度,InnoDB 将动态增加刷新速度超过此限制。第二个选项定义了对 InnoDB 可以将刷新率提高多远的更严格限制。
如果刷新的速度可以跟上创建新脏页的平均速度,那么你会没事的。但是,如果您始终创建脏页的速度快于它们被刷新的速度,最终您的缓冲池将被脏页填满,直到脏页超过缓冲池的innodb_max_dirty_page_pct
。此时刷新率会自动增加,可能会再次导致page_cleaner发送警告。
另一个解决方案是将 MySQL 放在具有更快磁盘的服务器上。您需要一个能够处理页面刷新所需吞吐量的 I/O 系统。
如果您在平均流量下一直看到此警告,则您可能试图在此 MySQL 服务器上执行过多的写入查询。可能是时候进行横向扩展,并将写入拆分到多个 MySQL 实例上,每个实例都有自己的磁盘系统。
阅读有关页面清洁器的更多信息:
Introducing page_cleaner thread in InnoDB(存档副本) MySQL-5.7 improves DML oriented workloads【讨论】:
将 innodb_lru_scan_depth 设置为 256 并没有解决问题 @KarimSamir,值 256 没有什么特别之处。这是 OP 使用的示例。 是的,我知道,你能建议我做些什么来解决这个问题吗? @KarimSamir,(1) 尝试其他小于 256 的值,(2) 获得更快的存储速度。 还有一件事如何永久更改 innodb_lru_scan_depth ?【参考方案2】:瓶颈是将数据保存到硬盘。无论您使用哪种硬盘:SSD、普通硬盘、NVMe 等。
请注意,此解决方案主要适用于 InnoDB
我有同样的问题,我已经应用了几个解决方案。
1st:检查问题所在
atop -d
将显示磁盘使用情况。如果磁盘“忙”,则尝试停止对数据库的所有查询(但不要停止 mysql 服务器服务!)
要监控您有多少查询,请使用 mytop、innotop 或等效项。
如果您有 0 个查询,但磁盘使用率在几秒/几分钟后仍然接近 100%,那么这意味着 mysql 服务器正在尝试刷新脏页/如前所述进行一些清理(伟大的帖子比尔·卡尔文)。
那么你可以尝试应用这样的解决方案:
第二:硬件优化
如果您的阵列不在 RAID 1+0 中,请考虑使用此类解决方案将数据保存速度提高一倍。尝试通过写入数据来扩展 HDD 控制器的可能性。尝试使用 SSD 或更快的 HDD。应用此方案取决于您的硬件和预算可能性,并且可能会有所不同。
第三:软件调优
如果硬件控制器工作正常,但你想提高保存数据的速度,你可以在 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
上面的行禁用保存日志,当然这是另一个要保存在硬盘上的数据量
3.4 再次检查正在发生的事情,例如 tail -f /var/log/mysql/error.log
4th:一般说明
一般说明:
这是在 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
服务器内存总量:200GB
这样做之后,您可能会观察到更高的 CPU 使用率;这很正常,因为写入数据更快,所以CPU会更努力。
如果您使用 my.cnf 进行此操作,当然不要忘记重新启动 MySQL 服务器。
第五:补充
出于好奇,我做了这个怪癖
SET GLOBAL innodb_lru_scan_depth=256;
上面提到过。
使用大表时,我发现性能没有任何变化。
经过上述更正后,我并没有消除警告,但是整个系统的运行速度明显加快。 以上只是一个实验,但我已经测量了结果,它对我有一点帮助,所以希望它对其他人有用。
【讨论】:
非常详细的解释,将研究实现它。谢谢 @Vilq 感谢您的解释 伙计们!使用 SSD 驱动器时,不要忘记,写入速度几乎与普通旋转驱动器相同......我做了几次测试,我很失望。它真的不能更快地使用数据库,这不是一个“正常”的应用程序。以下是为什么使用 SSD 驱动器的数据库的基准测试无用的解释:link。真的,没想到SSD这么慢…… 仔细阅读第 3.2 步,这对于生产服务器来说是不安全的。 https://dba.stackexchange.com/questions/86636/when-is-it-safe-to-disable-innodb-doublewrite-buffering 非常好的帖子顺便说一句,我一直在测试你提到的其他步骤,在我的情况下仍然没有运气,但它可能有帮助:) 对于innodb_flush_log_at_trx_commit
,“完全符合 ACID 要求需要默认设置 1”。来源:dev.mysql.com/doc/refman/5.7/en/…【参考方案3】:
这通常表明文件系统性能不佳 - 一个不相关问题的症状。就我而言,我花了一个小时研究这个,分析我的系统日志,并且几乎达到了调整 MySQL 配置的地步,当我决定检查我的基于云的托管时。事实证明存在“来自邻居的滥用 I/O 峰值”。在我提请他们注意后,我的主人很快就解决了这个问题。
我的建议是了解您的基准/预期文件系统性能,停止 MySQL,并测量您的文件系统性能以确定是否存在更多与 MySQL 无关的基本问题。
【讨论】:
以上是关于如何解决 mysql 警告:“InnoDB:page_cleaner:1000ms 预期循环花费了 XXX 毫秒。设置可能不是最佳的”?的主要内容,如果未能解决你的问题,请参考以下文章