MySQL,平均负载,查询缓存以及“数据发送”

了解现今有关MySQL的新事物,或者至少去观察一些新事物。

我们有非常庞大的Drupal系统,约有10个Web服务器,5个MySQL服务器,运行着标准的MySQL 5.1数据库(非Percona等版本)。

关键问题在于,其中一个数据库系统平均负载125-200 。想象一下,这是在一个有着8个CPU的服务器上。通常情况下,这意味着有非常高的CPU负载或非常高的I/O 。并且,只有非常繁忙的Web服务器才会出现平均负载超过100的情况。

但是,该服务器的CPU和I/O都非常低,大概都只有5 % 。同时,vmstat工具能够看到很少的运行中的进程或被禁止的进程,这是观察平均负载的典型方式。

这是怎么回事呢?

当整个MySQL进程列表显示“发送数据”的状态持续多达一两分钟的时候,我就认为这是网络不好了。所以我认为我要么遇到了网络问题(有些服务器已接近1Gbps),要么就是网卡坏了,或者一些奇怪的或随机的东西在阻止数据库发送信息。

我不知道出了什么情况,有一段时间就完全放弃了,我把这台服务器从负载均衡器下读数据库的负载均衡池中撤出。直到后来我关掉查询缓存时,我在另一个从属服务器上发现了问题所在。

为什么要关闭查询缓存?

这个系统有一些主要问题已经过去一周了还没解决,这可能与内部的Drupal有关。基本上,Drupal能每秒瞬间发送3 – 5000个查询到数据库子系统。对于同一个查询,MySQL能根据日志快速作出应答,大概50微妙。

要如此快速地作出应答只有一个办法:查询缓存。这一点非常了不起,但在这个查询层次上,每一个从属数据库服务器需要达到1000/秒,并且全部用于同一个查询,这意味着查询缓存的内部锁定是低负担分时系统,而我们知道这样的情况是不利的。

因为没有CPU ,没有日志,我们几乎什么都看不到,进程列表中没有一样东西是处于非睡眠状态的,完全没有。有的只是大量快捷的查询。但这些查询还不够快,因为锁定与查询量之间的相对造成了前端缓慢。

所以我关掉了另一台从属服务器上面的查询缓存,然后事情变得有趣了。负载直接进入到了InnoDB,同时CPU跃升至75%。更有意思的是,我有100个以上的查询在InnoDB队列中等待(直到我把并发InnoDB 提升到256)。此外,Innodb的状态显示有几十个或者更多个信号量被锁定,因为5.1的Innodb伸缩性并不好(不使用外挂程序)。

所有这些在某种程度上会阻塞线程并给我带来高得吓人的平均负载,100 +。另外,这种锁定状态不知怎么得会以“发送数据”的状态显示在进程列表中,这的确令人困惑(尽管这种状态并不意味着它在获取和发送数据)。

最后想法

最后,我重新打开了查询缓存,因为这样可能会更快,但这整个过程非常有趣,下次再遇到这样的情况的时候你就知道该怎么做了。没有CPU和IO的情况下,极高的平均负载可能是因为查询缓存处于高并发的状态。

以后我们会升级到Percona 5.5,努力缓解争用,而客户开发团队负责修复Drupal来消除这种疯狂的负荷。我们并非每天都能在一个明显闲置的数据库上看到每秒有1000个相同查询和250的平均负载。

这种情况对于我们来说已经是司空见惯了,因为我们为全世界成千上万的用户构建和管理数以百计的大型MySQL系统。但是我们每天都在学习新的东西。


Tags: MYSQL
Categories: Databases

发表评论

电子邮件地址不会被公开。 必填项已用*标注

* Copy This Password *

* Type Or Paste Password Here *