我们正在运行一个分布在三个服务器上的网站。 其中两个是负载平衡的Web服务器,最后一个是专用的MySQL服务器。 mysql服务器使用2.6.18-92.1.6.el5#1 SMP内核和MySQL 5.0.45运行RHEL5 64位。 这也是一个非常强大的服务器,与至强L5420和8演出的RAM。 我们的Web服务器的PHP页面被configuration为使用mysqli。
通常情况下,我们并没有真正利用所有的资源,白天我们做了20-25次查询。 但是,每隔一段时间,我们都会在最大的数据库连接数限制内进行攻击,而且我们的网站也会遭到谴责。 更重要的是,这似乎是晚上发生的,网站的stream量应该是最低的。
我们开始在100个最大的连接,我们把它boost到300,但它仍然发生。 如果它有所作为,我们注意到有时会有大量的睡眠MySQL进程,但是没有任何连接到数据库的东西使用持久连接。 这不是每天晚上都会发生,我们有一些问题,每天晚上都会发出哗哗的声音,直到今天大约一个半星期的时间。
我们没有任何怪物查询,一次只能logging数据库的分钟数。 我们已经试过了SLOW_QUERY日志。 我们有几个查询出现在那里,但通常他们不会持续超过1或2秒,这是很less见的。
这听起来像什么特别? 在诊断问题方面,我们将如何从这里开始?
我的猜测是,你的应用程序中有一些长时间运行的查询。 当它们被执行时,它们导致连接长时间停留在池外(相对于通常的使用模式),这会导致你的池变得枯竭,增长,并继续增长到最大值,在此时任何剩余的工人阻止等待连接被释放。
第一件事就是在发生这种情况时追查,也就是说,这是一个周期性事件还是随机的。 如果它的前者,你运气好,因为你可以准备好时间它发生。 如果你不能确定一个模式,那么你必须保持警惕。
您可以通过查看您的网站监控日志,或者从您的数据库中查看是否有任何相关的峰值。
如果你的数据库在加载的时候可以捕获,你应该在mysql服务器上执行以下命令
show innodb status; show processlist;
前者将打印出关于innodb引擎的诊断信息(您正在使用innodb?),后者将打印出正在执行的查询的前几百个字符。 查找已经运行了很长时间的查询,在磁盘上生成临时表的查询以及在资源上被阻塞的查询。
之后,艰苦的工作就开始了。 使用EXPLAIN来估计查询的成本及其使用的资源。 避免需要通过tmp表在磁盘上sorting的查询。 查找长时间运行的报告作业或定期locking或饱和数据库的其他计划维护任务。 这可能与备份任务一样简单,也可能是汇总旧采购订单数据的作业。
我build议在你的/etc/my.cnf有这三个设置
log_slow_queries log-queries-not-using-indexes set-variable = long_query_time=1
对于每秒执行20-30次请求的Web应用程序,您不能在这些日志中显示任何内容。
顺便说一句,恕我直言,它没有意义的增加您的连接池的大小超出您的原始大小,因为这只会延迟池的耗尽最多,几秒钟的开始,只有当你不需要的时候给你的分区权利更多的压力。
我以前见过这个。
我们有一个cron使用MyISM表执行数据库的mysqldump。 由于MyISM的mysql转储会locking整个表。 导致查询(因此连接)排队。
AlexMax,哪里可以解决这个问题? 虽然存在差异,但我目前也看到类似的问题,正如你在这里描述的那样,14台networking服务器负载平衡到8台MySQL服务器(每个网站都被编码为一台networking服务器)。 连接将会激增,并且mysql的进程列表中有90%以上被列为睡眠,并且具有查询NULL。 这将使MySQL停止允许连接并持续约。 2-3分钟。 四Xeons上的Mysql 5.0.70和PHP 5.28(尽pipe我们是32位的)。