没有做任何更改,但MySQL InnoDB重载CPU

我还没有改变任何脚本或设置。 现在我的CPU负载至less高出4倍。 根据TOP,Mysqld占据了360%左右的CPU。 这是Debian,我正在运行一些MyISAM表,但大多数是InnoDB。 我已经validation了使用InnoDB的站点上线时负载变得很高。 即使在现在的夜晚,当总体负荷通常在1以下时,也有12个。我不知道哪里出了问题。 我没有改变任何东西。 我已经尝试完全重新启动机器。

我改变了我的innodb_log_file_size为2047M,而不是512M,负载没有明显的改善。 其他的my.cnf微调部分:

key_buffer = 4000M max_allowed_packet = 32M thread_stack = 256K thread_cache_size = 192 myisam-recover = BACKUP max_connections = 10000 query_cache_limit = 1M query_cache_size = 256M innodb_buffer_pool_size=8G innodb_additional_mem_pool_size=20M sort_buffer=2M thread_concurrency=16 record_buffer=2M tmp_table_size=128M max_heap_table_size=128M table_cache=1024 innodb_log_file_size = 2047M innodb_log_buffer_size = 16M innodb_flush_log_at_trx_commit = 2 innodb_file_per_table innodb_flush_method = O_DIRECT 

这是24GB RAM机器运行Apache和MySQL。 每天有大约20k次访问。 在这一刻,仍然有20GB的内存(这是晚上,我刚刚重新启动)。 系统硬盘只占8%。 所有硬盘似乎都以适当的速度写入/读取。

我的configuration有问题吗? 即使我没有更改任何服务器机器设置或PHP脚本,负载翻转是否可能? 还有什么可能导致这个?

编辑:从vmstat输出

 vmstat 5 10 procs -----------memory---------- ---swap-- -----io---- -system-- ----cpu---- rb swpd free buff cache si so bi bo in cs us sy id wa 13 1 868 280368 179164 18089764 0 0 511 579 16 89 87 2 10 1 24 2 868 348948 183916 18136144 0 0 5791 610 1916 7552 89 2 7 1 23 0 868 501744 185972 18169456 0 0 3995 5877 2401 6277 91 3 5 1 6 0 868 694992 186136 18202684 0 0 3385 4783 1006 5958 91 2 7 0 22 0 868 825240 186372 18243540 0 0 4133 4087 1098 5364 91 2 7 0 19 0 868 284452 186540 18281960 0 0 3907 4380 537 6468 91 3 7 0 44 0 868 123408 177236 17022560 0 0 3896 5173 483 6914 88 5 7 0 17 0 868 159388 173236 16729360 0 0 4625 8856 1433 7072 89 3 8 0 14 0 868 248836 173380 16763992 0 0 5284 698 819 7357 88 2 9 0 15 0 868 406092 173592 16809708 0 0 4730 5794 1148 7224 90 2 8 0 

ps -eo命令,pid,ppid,%cpu,%mem,rss,pri,psr,size –sort = – %cpu | head -n 20

 COMMAND PID PPID %CPU %MEM RSS PRI PSR SZ /usr/sbin/mysqld --basedir= 379 342 364 11.1 2747020 19 1 14249120 gzip 5537 5536 30.1 0.0 756 0 3 452 /usr/sbin/apache2 -k start 2435 27735 6.6 0.3 75408 19 1 47184 /usr/sbin/apache2 -k start 2388 27735 6.7 0.3 77928 19 3 48144 /usr/sbin/apache2 -k start 2323 27735 5.9 0.3 79660 19 3 48464 /usr/sbin/apache2 -k start 2363 27735 5.8 0.3 77156 19 4 47256 /usr/sbin/apache2 -k start 2418 27735 5.7 0.3 77248 19 7 46684 /usr/sbin/apache2 -k start 2350 27735 5.8 0.3 78504 19 2 48092 /usr/sbin/apache2 -k start 2437 27735 5.5 0.3 75928 19 3 47436 /usr/sbin/apache2 -k start 2439 27735 5.5 0.3 75716 19 3 47596 /usr/sbin/apache2 -k start 2356 27735 5.7 0.3 78560 19 3 48708 /usr/sbin/apache2 -k start 2284 27735 5.6 0.3 79532 19 3 47896 /usr/sbin/apache2 -k start 2349 27735 5.6 0.3 78248 19 7 48548 /usr/sbin/apache2 -k start 2368 27735 5.6 0.3 77100 19 3 45852 /usr/sbin/apache2 -k start 2387 27735 5.5 0.3 79964 19 7 48952 /usr/sbin/apache2 -k start 2383 27735 5.4 0.3 79212 19 1 48448 /usr/sbin/apache2 -k start 2169 27735 5.4 0.3 81740 19 3 48636 /usr/sbin/apache2 -k start 2411 27735 5.3 0.3 77292 19 3 47628 /usr/sbin/apache2 -k start 1779 27735 5.4 0.3 88876 19 0 48384 

mpstat 5 10

 Linux 2.6.26-2-amd64 12/12/2014 _x86_64_ 03:38:23 PM CPU %user %nice %sys %iowait %irq %soft %steal %idle intr/s 03:38:28 PM all 87.44 3.56 1.44 0.17 0.15 0.40 0.00 6.83 2363.80 03:38:33 PM all 86.82 3.31 1.82 0.12 0.05 0.25 0.00 7.62 1703.00 03:38:38 PM all 88.52 2.39 1.76 0.30 0.15 0.32 0.00 6.56 2552.68 03:38:43 PM all 85.12 3.92 2.17 0.27 0.10 0.42 0.00 7.99 2810.60 03:38:48 PM all 87.72 3.34 1.82 0.10 0.10 0.30 0.00 6.61 2368.00 03:38:53 PM all 85.36 3.83 1.59 0.40 0.05 0.17 0.00 8.59 1589.60 03:38:58 PM all 85.74 4.01 1.50 0.20 0.07 0.17 0.00 8.30 1648.00 03:39:03 PM all 85.26 4.16 1.75 0.20 0.12 0.60 0.00 7.91 1764.20 03:39:08 PM all 87.20 3.62 1.70 0.17 0.10 0.45 0.00 6.76 2221.80 03:39:13 PM all 85.96 3.12 2.67 0.27 0.05 0.52 0.00 7.41 2829.60 Average: all 86.52 3.53 1.82 0.22 0.09 0.36 0.00 7.46 2185.35 

编辑,MySQL 5.5

升级到MySQL 5.5实际上有很大的不同。 负荷从20日降至10日,晚上从10日降至6日。 交通接近无=负载6,高交通=负载10。

=>现在有趣的是,当前的负载正好比事件之前的值高出5个点 。 不pipe交通。 这实际上并没有太大的意义。 没有理由在8核CPU上加载6几乎没有stream量,更奇怪的是,负载只有在交通繁忙时加倍 。 日负荷曾经比夜晚高5倍

==> MySQL 5.5是奇迹般的高效率(相对于5.0),或者是有什么东西,无论如何总共加起来5分。 虽然我看不到任何特殊的过程。 它必须是Apache / PHP / MySQL相关的。

编辑,解决(本身)

4天前,负载在天空,没有明显的原因。 今天清晨,负载就像这样降到正常值。

在这里输入图像说明

我不是那种把DDOS归咎于一切的粉丝,我通过查看networking统计数据来排除这一点。 但是再一次,我从来没有经历过任何攻击,我可能不认识它。

事实:三天之后,我已经升级到了MySQL 5.5,但是没有完全解决这个问题,但是降低了足够的负载,使站点在访问者端再次顺利。 一天之后,问题就消失了。 当这个网站没有长时间的加载时间,就好像有人失去了兴趣。

操作系统腐败本身并不会消失。 没有后台任务。 攻击似乎是唯一的左边的解释,虽然我没有注意到任何奇怪的networking活动。 有一件事我可以说,我们的观众正是那种经常做这种事情的人。

编辑29/12/2014

我不确定是否有人在看这个post。 我只想发布更新。 高负荷回来后,几天,然后去了夫妇,回来等有时负荷不断高,有时它尖峰。 一天可以下降50%,再上涨100%。 时间不同 – 与实际交通,后台任务没有任何关系。 虽然它看起来像DDOS,但没有奇怪的networking活动。

MySQL 5.5的最大区别在于,现在机器可以更好地处理任何正在耗费资源的工作,从而保持网站正常运行。 瓶颈似乎又是CPU,再次没有多大意义。

最“有趣”的是这种行为的不可预测性。 这只是不适合任何软/硬件故障, 或者是否

毫无疑问,我坚信这是InnoDB存储引擎。

它几乎就像一个活生生的呼吸有机体。

这里是来自Percona首席技术官Vadim Tkachenko的图片展示

InnoDB架构

请注意InnoDB缓冲池。 如果它有很多脏页(改写回写入物理表)和相应的索引更改(缓冲池的插入缓冲区),请注意以下写入

  • 将I / O线程从缓冲池写入.ibd文件(物理表文件)。 这可能需要读/写I / O,可能通过LRUalgorithm打开和closures表
  • 系统表空间文件(ibdata1)中插入缓冲区写入的更改
  • 由于您有innodb_flush_log_at_trx_commit = 2,日志缓冲区每秒刷新一次(而不是hibernate系统中的问题,因为innodb_log_buffer_size是16,在重写过程中可能是一个问题)
  • 肮脏的页面被写入双写缓冲区(帮助mysqld在mysqld崩溃中幸存下来(或者至less有相当数量的InnoDB损坏控制))

讨论InnoDB存储引擎有什么意义?

如果整个工作日都有很多脏页面,那么可能会有一些活动来冲洗引擎周围的变化,如心脏循环血液。 即使是轻微的写入也可以隐藏。 既然你有一个2G缓冲池, InnoDB可能只是在冲刷缓冲池(通过它的清除线程) 。

从my.cnf的样子,我会说你可能有MySQL 5.5或更高版本。 InnoDB在没有调整的情况下,往往对清除线程更具攻击性。

现在,一个惊喜。 你知道InnoDB可以保持安静,至less有75%的缓冲区仍然脏吗?

  • MySQL 5.5和5.6 ,innodb_max_dirty_pages_pct = 75
  • MySQL 5.0和5.1 ,innodb_max_dirty_pages_pct = 90

这意味着如果InnoDB不能容忍超过75%(或90%)的脏页面。 当脏页面超过innodb_max_dirty_pages_pct的阈值时,它开始主动清除线程活动。 一旦低于75%或90%的阈值,InnoDB将会稳定地清除脏页面, 当它是好的和准备好的时候 。 即使在没有INSERT,UPDATE和DELETE的情况下,这也performance为写入I / O,服务器负载和增加的CPU。 尽pipe如此,InnoDB将决定何时需要清除旧的脏页面。

你可能需要的只是一些调整。 以下是您需要的一些设置示例

 [mysqld] innodb_read_io_threads = 16 innodb_write_io_threads = 16 innodb_thread_concurrency = 0 

为了更深入的了解InnoDB是否搞了更多的超线程和CPU,请参阅我的DBA StackExchange文章:

  • 有可能使MySQL使用多个核心?
  • 在Debian上使用多个核心进行单个MySQL查询
  • 关于单线程与multithreading数据库的性能

顺便说一句,你有24GB的RAM和只有2GB缓冲池? 请看我的旧postmysql应该是多大的innodb_buffer_pool_size? 。 为什么? 即使对超线程和CPU进行了适当的调整,尺寸不足的缓冲池仍然可能会间歇性地被写出来。

更新2014-12-12 10:30 EST

由于您现在在MySQL 5.0,所以您可以使用以下设置尽可能彻底地进行清理:

 [mysqld] innodb_thread_concurrency = 0 innodb_max_dirty_pages_pct = 0 

这应该最小化,或者至less减less负载和CPU突然上升的发生

这些是可选的

 [mysqld] innodb_fast_shutdown = 0 innodb_flush_log_at_trx_commit = 1 sync_binlog = 1 

为什么这些可选设置?

  • 设置innodb_fast_shutdown = 0
    • 确保所有事务都被刷新到磁盘
    • 使得启动速度更快
  • innodb_flush_log_at_trx_commit设置为1可正确刷新表和重做日志。 CAVEAT:某些硬件可能仍然不响应此设置。
  • 如果启用了二进制日志logging,则sync_binlog将正确刷新二进制日志

长期来看,你需要真正需要MySQL 5.6。

这个问题与存储引擎无关,问题可能是因为很less的SQL查询正在为特定的站点/应用程序处理太高的CPU资源。 这可能是因为查询使用“未索引”列或查询效率不高。 更好地理解这个问题在mysql上启用“慢查询”日志。

 log_slow_queries=/var/log/mysql/slow-query.log long_query_time=1 

以上设置将导致需要超过1秒的查询才能login/var/log/mysql/slow-query.log 。 稍后,您可以参考日志来识别查询并对其进行微调。

识别问题的另一种方法是检查使用SHOW FULL PROCESSLIST命令来获取当前正在运行的查询的列表。 通过查看,你可以缩小什么样的查询导致这个问题。

并粘贴vmstat 5 10的输出。 这将有助于查找是否有任何硬件瓶颈。