MySQL 连接突然突飞猛进

Ale*_*Max 6 mysql rhel5

我们正在运行一个分布在三个服务器上的网站。其中两个是负载平衡的 Web 服务器,最后一个是专用的 mysql 服务器。mysql 服务器使用 2.6.18-92.1.6.el5 #1 SMP 内核和 MySQL 5.0.45 运行 RHEL5 64 位。它也是一个非常强大的服务器,配备至强 L5420 和 8 演出内存。我们的 Web 服务器的 php 页面被配置为使用 mysqli。

通常我们不会真正利用我们提供的所有资源,我们在白天每秒执行 20-25 次查询。然而,每隔一段时间,我们就会一头扎进最大数据库连接限制,而我们的网站也会因此而嘎嘎作响。更重要的是,它似乎发生在晚上,网站的流量应该是最低的。

我们开始时最大连接数为 100,我们将其提高到 300,但它仍然发生。如果它有所不同,我们会注意到有时有大量的 MySQL 进程处于休眠状态,但连接到数据库的任何进程都没有使用持久连接。它不会每晚都发生,我们遇到了一些问题,它每晚都会发出嘶嘶声,然后在大约一个半星期之前都很好,直到今天。

我们没有任何会占用数据库几分钟的怪物查询。我们尝试浏览 SLOW_QUERY 日志。我们有一些查询显示在那里,但通常它们不会持续超过 1 或 2 秒,而且这种情况很少见。

这听起来有什么特别的吗?在诊断问题方面,我们将如何从这里开始?

Dav*_*ney 6

我的猜测是您的应用程序中有一些长时间运行的查询。当它们被执行时,它们会导致连接长时间保持在池外(相对于通常的使用模式),这会导致您的池耗尽、增长并继续增长到最大值,此时任何剩余的工作人员都会阻止等待释放的连接。

第一件事是追踪何时发生这种情况,即它是周期性事件还是随机事件。如果是前者,那么您很幸运,因为您可以在它发生的时候做好准备。如果你不能确定一个模式,那么你就必须保持警惕。

您可以通过查看您的网站监控日志或sar从您的数据库中查看是否存在任何相关尖峰来计算出这一点。

如果您可以在负载不足时捕获数据库,则应在 mysql 服务器上执行以下命令

show innodb status;
show processlist;
Run Code Online (Sandbox Code Playgroud)

前者将打印出有关 innodb 引擎的诊断信息(您正在使用 innodb 对吗?),后者将打印出正在执行的查询的前几百个字符。查找已运行很长时间的查询、在磁盘上生成临时表的查询以及在资源上被阻止的查询。

在那之后,艰苦的工作开始了。使用EXPLAIN估计查询的成本,而且它使用的资源。避免需要通过 tmp 表在磁盘上排序的查询。查找长时间运行的报告作业或其他定期锁定或使数据库饱和的计划维护任务。它可以像备份任务一样简单,也可以是一项汇总旧采购订单数据的工作。

我建议在您的 /etc/my.cnf

log_slow_queries
log-queries-not-using-indexes
set-variable = long_query_time=1
Run Code Online (Sandbox Code Playgroud)

对于每秒处理 20-30 个请求的 Web 应用程序,您不能在这些日志中显示任何内容。

顺便说一句,恕我直言,将连接池的大小增加到超出原始大小是毫无意义的,因为这最多只会延迟池耗尽的开始,最多几秒钟,并且只会在不需要时对数据库施加更大的压力。