编辑,MySQL 5.5

编辑,MySQL 5.5

我没有更改任何脚本或设置。现在我的 CPU 负载至少高出 4 倍。根据 TOP,Mysqld 占用了大约 360% 的 CPU。这是 Debian,我正在运行一些 MyISAM 表,但大多数是 InnoDB。我已经验证了当使用 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。每天大约有 2 万次访问。目前仍有 20GB RAM 可用(现在是晚上,我刚刚重新启动)。系统硬盘只占用了 8%。所有硬盘似乎都在以适当的速度写入/读取。

我的配置有问题吗?即使我没有更改任何服务器机器设置或 PHP 脚本,负载是否也可能突然升高?还有什么可能导致这种情况?

编辑:vmstat 的输出

vmstat 5 10
procs -----------memory---------- ---swap-- -----io---- -system-- ----cpu----
 r  b   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 分高于事件发生前的值。无论流量如何。这对我来说真的没有多大意义。几乎没有流量的情况下,8核CPU上没有理由加载6,更奇怪的是,加载仅双倍交通繁忙时。日负荷过去高出 5 倍比夜晚。

==> 要么是 MySQL 5.5 的效率高得惊人(与 5.0 相比),要么是无论如何都有某种东西可以增加这 5 分。但我看不出有什么特殊过程。它一定与 Apache/PHP/MySQL 有关。

编辑,已解决(自行解决)

4天前,负载突然无缘无故地飙升。今天凌晨,负载就这么降到了正常值。

在此处输入图片描述

我并不喜欢把所有问题都归咎于 DDOS,事实上,我通过查看网络统计数据排除了这种可能性。但话又说回来,我从未经历过任何攻击,我可能没有意识到。

事实:3 天后,我设法升级到 MySQL 5.5,虽然没有完全解决问题,但降低了负载,使网站在访问者端再次变得顺畅。一天后,问题消失了。这几乎就像有人在网站没有长时间加载时失去了兴趣。

操作系统损坏不会自行消失。没有后台任务。攻击似乎是唯一剩下的解释,尽管我没有注意到任何奇怪的网络活动。我可以说的是,我们的观众正是经常做这种事情的人。

编辑2014年12月29日

我不确定是否有人还在关注这个帖子。我只是想发布一个更新。几天后,高负载又回来了,然后几天后又消失了,又回来了等等。有时负载持续很高,有时突然上升。一天可以下降 50%,另一天又上升 100%。时间不同——与实际流量、后台任务等没有任何关系。虽然它看起来确实像 DDOS,但没有奇怪的网络活动。

不过,最大的不同是 MySQL 5.5,现在机器可以更好地处理消耗其资源的任何事情,保持网站正常运行。瓶颈似乎再次是 CPU,这又没有多大意义。

最“搞笑”的是这种行为的不可预测性。这真的不符合软件/硬件的任何错误,或者??

答案1

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

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

以下是 Percona 首席技术官 Vadim Tkachenko 的图示

InnoDB架构

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

  • 将 I/O 线程从缓冲池写入 .ibd 文件(物理表文件)。这可能需要读/写 I/O,可能通过 LRU 算法打开和关闭表
  • 对插入缓冲区写入系统表空间文件 (ibdata1) 的更改
  • 由于您有 innodb_flush_log_at_trx_commit = 2,日志缓冲区每秒刷新一次(在休眠系统中这不是问题,因为 innodb_log_buffer_size 为 16,但在大量写入期间可能会出现问题)
  • 脏页被写入双写缓冲区(帮助 mysqld 在 mysqld 崩溃时存活下来(或者至少是相当数量的 InnoDB 损害控制))

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

如果整个工作日中有大量脏页被写入,那么可能会有一些活动像心脏循环血液一样在引擎周围清除更改。即使是轻微的写入也可以隐藏一段时间。由于您有 2G 缓冲池,InnoDB 可能只是在搜索缓冲池(通过其清除线程)

从 my.cnf 来看,我认为你可能使用的是 MySQL 5.5 或更高版本。InnoDB 在未进行调整时,往往会更积极地处理清除线程

现在,令人惊讶的是,您是否知道即使至少 75% 的缓冲区仍是脏的,InnoDB 仍可以保持安静?

  • MySQL5.55.6,innodb_max_dirty_pages_pct = 75
  • MySQL5.05.1,innodb_max_dirty_pages_pct = 90

这意味着 InnoDB 不会容忍超过 75%(或 90%)的脏页。当脏页超过阈值时,它会启动积极的清除线程活动innodb_max_dirty_pages_pct。一旦它低于 75% 或 90% 的阈值,InnoDB 将稳定地刷新脏页当一切准备就绪时。即使没有进行 INSERT、UPDATE 和 DELETE,这也表现为写入 I/O、服务器负载和 CPU 增加。尽管如此,InnoDB 仍会决定何时需要清除真正旧的脏页。

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

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

要深入了解如何让 InnoDB 使用更多超线程和 CPU,请参阅我的 DBA StackExchange 帖子:

顺便问一下,你有 24GB 的 RAM,但缓冲池只有 2GB?请参阅我的旧帖子mysql 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

这应该可以最大限度地减少或至少减少负载和 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 即可正确刷新到表和重做日志。注意:某些硬件可能仍然不响应此设置。
  • 如果你启用了二进制日志记录,sync_binlog将正确刷新二进制日志

从长远来看,您确实需要使用 MySQL 5.6。

答案2

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

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

上述设置将导致处理时间超过 1 秒的查询被记录下来/var/log/mysql/slow-query.log。稍后您可以参考日志来识别查询并对其进行微调。

识别问题的另一种方法是使用SHOW FULL PROCESSLIST命令检查当前正在运行的查询列表。通过查看它,您可以缩小导致此问题的查询类型范围。

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

相关内容