esw*_*ald 6 mysql performance innodb
我们使用 InnoDB 表作为 Web 应用程序的后端,在大约两年前一切都很好,直到几周前我们不得不重新启动 MySQL。(我们没有禁用反向 DNS 查找,即使我们并没有真正使用它们,但是我们的托管系统突然停止响应这些请求。它们现在已被禁用。)不幸的是,配置文件已更改,我们没有t 有其原始状态的副本以供比较。
在解决了最重要的问题之后,我们遇到了一个真正的难题:在高负载下,数据库查询开始花费比平时更长的时间。在这种情况下,我们的七个 apache 服务器有数百个打开的连接。运行 SHOW PROCESSLIST 显示这些连接中有一半或更多处于“发送数据”状态,时间通常为几百秒。他们几乎所有的查询都是 SELECT,类似的查询往往会聚集在一起。事实上,列表中最低的一组往往是完全相同的查询(我希望它在查询缓存中),返回 1104 行,每行两个整数。其他常见的违规行为是包含数百个单整数行、几个单整数行,甚至是单个 COUNT(*) 结果的列表。
我们尝试在其中一个期间关闭 Web 服务器,但问题在重新启动后一分钟内再次出现。但是,完全重新启动 mysqld 解决了问题,直到第二天。问题可能是什么,我们如何验证和/或修复它?
好吧,请注意,如果我没记错的话(自从我从事 DB 工作以来已经有一段时间了)在 innodb 表上没有 WHERE 子句的 COUNT(*) 查询比在 MyISAM 和 Memory 表上慢是出了名的慢。
另外,这是 Xen DomU 吗?
什么是前端语言?如果是 PHP,它使用的是 MySQL 还是 MySQLi?他们是否使用持久连接?
你没有提到底层操作系统,但在 Linux 的情况下,我会先盯着 的输出free -m,特别注意最后两行,看看整体内存是否紧张。
[0:504] callisto:cyanotype $ free -m
total used free shared buffers cached
Mem: 3961 3816 144 0 184 1454
-/+ buffers/cache: 2177 1784
Swap: 2898 0 2898
Run Code Online (Sandbox Code Playgroud)
这里我们有一个健康的系统(它是我的工作站)。第二列不包括缓冲区和缓存,所以我实际上使用了 2177 mb 的内存,并且有 1784 兆字节随时可用。
最后一行显示到目前为止我根本不使用交换。
然后给vmstat(8), 看看你的系统是否像疯了一样垃圾也会很有用。
[0:505] callisto:cyanotype $ 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
0 0 0 134116 189828 1499948 0 0 11 3 44 49 1 1 98 0
0 0 0 143112 189836 1489688 0 0 0 6 526 2177 1 1 98 0
0 0 0 139268 190504 1491864 0 0 512 4 663 4704 2 1 96 1
2 0 0 136688 191084 1493484 0 0 473 5 641 3039 1 1 97 1
0 0 0 52636 191712 1518620 0 0 5066 4 1321 6600 8 2 86 4
5 0 0 72992 193264 1377324 0 0 10742 31 1602 7441 12 3 80 5
2 1 0 84036 193896 1202012 0 0 10126 43 2621 4305 31 2 57 10
3 0 0 42456 195812 1060904 0 0 3970 75 55327 9806 43 5 41 10
8 1 0 34620 197040 942940 0 0 3554 64 50892 12531 43 6 44 6
^C
[0:506] callisto:cyanotype $
Run Code Online (Sandbox Code Playgroud)
(我的桌面在这里真的没有做那么多,抱歉。浪费了 8 个完美的内核)
如果您在“b”列中看到大量进程花费时间,则意味着它们被阻塞,等待某些事情。通常这就是 IO。这里的重要列是si和so。检查它们是否填充了高值。如果是这样,这可能是您的问题——某些东西正在消耗大量内存,超出了您的实际负担。top(4)按内存百分比使用和排序列(在顶部时 shift+m)可能会显示罪魁祸首。
您的系统在交换区之间进行垃圾处理,并使磁盘饱和,导致线程和进程阻塞,这并非不可能。应该试一试该工具iostat(8)(sysstat通常是包的一部分),看看是否有进程被阻塞、卡住IO_等待。在高负载下,饱和磁盘可能会给整个系统带来坏消息,尤其是在系统进行大量交换的情况下。
您可以每五秒运行一次带有扩展统计信息的 iostat,例如:
[0:508] callisto:cyanotype $ iostat -x 5
Linux 2.6.35-23-generic (callisto) 2010-11-30 _x86_64_ (8 CPU)
avg-cpu: %user %nice %system %iowait %steal %idle
16,55 0,12 2,70 2,60 0,00 78,02
Device: rrqm/s wrqm/s r/s w/s rsec/s wsec/s avgrq-sz avgqu-sz await svctm %util
sdc 0,00 2,00 1,00 0,80 27,20 22,40 27,56 0,01 3,33 3,33 0,60
sdd 0,00 12,60 67,60 4,80 4222,40 139,20 60,24 0,62 8,62 3,29 23,80
sde 0,00 0,00 0,00 0,00 0,00 0,00 0,00 0,00 0,00 0,00 0,00
sdf 0,00 0,00 0,00 0,00 0,00 0,00 0,00 0,00 0,00 0,00 0,00
avg-cpu: %user %nice %system %iowait %steal %idle
32,02 0,10 1,83 0,44 0,00 65,61
Device: rrqm/s wrqm/s r/s w/s rsec/s wsec/s avgrq-sz avgqu-sz await svctm %util
sdc 0,60 3,20 11,00 0,80 265,60 32,00 25,22 0,05 3,90 2,88 3,40
sdd 0,00 8,20 0,00 3,00 0,00 89,60 29,87 0,02 8,00 7,33 2,20
sde 0,00 0,00 0,00 0,00 0,00 0,00 0,00 0,00 0,00 0,00 0,00
sdf 0,00 0,00 0,00 0,00 0,00 0,00 0,00 0,00 0,00 0,00 0,00
avg-cpu: %user %nice %system %iowait %steal %idle
49,26 0,22 3,12 0,12 0,00 47,28
Device: rrqm/s wrqm/s r/s w/s rsec/s wsec/s avgrq-sz avgqu-sz await svctm %util
sdc 6,20 3,00 7,40 3,80 208,00 54,40 23,43 0,09 7,86 2,50 2,80
sdd 0,00 15,20 0,20 4,00 1,60 152,00 36,57 0,03 6,67 6,19 2,60
sde 0,00 0,00 0,00 0,00 0,00 0,00 0,00 0,00 0,00 0,00 0,00
sdf 0,00 0,00 0,00 0,00 0,00 0,00 0,00 0,00 0,00 0,00 0,00
avg-cpu: %user %nice %system %iowait %steal %idle
16,00 0,54 1,05 1,07 0,00 81,35
Device: rrqm/s wrqm/s r/s w/s rsec/s wsec/s avgrq-sz avgqu-sz await svctm %util
sdc 4,20 0,00 31,40 0,00 3204,80 0,00 102,06 0,17 4,90 2,68 8,40
sdd 0,00 28,20 0,20 2,60 1,60 246,40 88,57 0,02 7,14 7,14 2,00
sde 0,00 0,00 0,00 0,00 0,00 0,00 0,00 0,00 0,00 0,00 0,00
sdf 0,00 0,00 0,00 0,00 0,00 0,00 0,00 0,00 0,00 0,00 0,00
^C
Run Code Online (Sandbox Code Playgroud)
这应该可以让您轻松查看您的交易量是否已饱和。例如,在这里,您可以看到我的磁盘未充分利用,系统将大部分 CPU 周期花费在空闲状态等。如果该百分比主要位于 % IOWAIT 列中,那么您在这里就有了 IO 瓶颈。您可能已经知道所有这些,但只是涵盖所有基础以确保。
这个想法是您的配置文件发生了更改,并且您没有它的历史记录(出于这个原因,将您的配置文件置于版本控制之下是一个好主意)-并且缓冲区的大小突然更改从而使成本变得昂贵并非不可能像 COUNT(*) 这样没有 SELECT 的查询突然开始吞噬资源。
根据您之前使用这些工具所学到的知识——您可能应该检查配置文件(这是唯一更改的内容,很可能是罪魁祸首)以查看缓冲区值对于您的平均负载是否合理.
缓冲区有多大,比如query_cache_size值,尤其是sort_buffer大小?(如果这不适合内存,它将在磁盘上执行,我相信您可以想象到的成本很高)。
有多大innodb_buffer_pool_size?
有多大table_cache,最重要的是,该值是否符合文件句柄的系统限制?([mysqld] 和操作系统级别的 open-files-limit)。
此外,我不记得这是否仍然正确,但我相当确定 innodb 在必须提交自动增量字段时实际上会锁定整个表。我用谷歌搜索,我找不到这是否仍然正确。
您还可以使用innotop(1)来更详细地查看正在发生的事情。
我希望这会有所帮助或为您提供一个起点:)
innodb_file_per_table事实证明,这是、default-storage-engine = innodb和创建临时表的频繁访问页面组合中的缺陷。每次连接关闭时,它都会删除该表,并丢弃缓冲池 LRU 中的页面。这会导致服务器停顿一会儿,但不会在真正导致问题的查询上停顿。
更糟糕的是,该innodb_file_per_table设置已经在我们的文件中滞留了my.cnf几个月,然后服务器因完全不相关的原因而不得不重新启动,在此期间我们一直在使用这些临时表而没有出现任何问题。(NOC 突然关闭了 DNS 服务器,导致每个新连接都挂起,因为我们没有启用 DNS 服务器skip-name-resolve,并且在几个小时内不承认任何事情发生了变化。)
幸运的是,我们能够重写有问题的页面,以使用一组更快的查询,将大部分工作加载到前端 Web 服务器上,从那以后就再也没有出现过问题。
| 归档时间: |
|
| 查看次数: |
28700 次 |
| 最近记录: |