我想我有一些应用程序问题会降低整个应用程序的速度,并可能造成损坏和其他问题 许多正在睡眠的mysql连接都会出现应用程序问题。
SHOW PROCESSLIST;
输出:
| 356058234 | Y | X:39119 | D | Sleep | 1442 | | NULL |
| 356058441 | Y | X:39126 | D | Sleep | 1442 | | NULL |
| 356059383 | Y | X:46615 | D | Sleep | 2049 | | NULL |
| 356059389 | Y | X:46617 | D | Sleep | 2052 | | NULL |
| 356065991 | Y | X:39267 | D | Sleep | 1442 | | NULL |
-------------
452 rows in set (0.00 sec)
另外mysqlreport
__ Connections _________________________________________________________
Max used 8001 of 8000 %Max: 100.01
Total 356.07M 58.6/s
这表明我的联系真的不多了。即使是8000的限制。这必须是一些东西。但调试这些东西可能会很麻烦。
无论如何,我用netstat查看了进程ID,例如像netstat -ntp | grep :39267
这样输出:
tcp 0 0 IP_1:3306 IP_2:38727 VERBUNDEN 791/mysqld
所以我更进一步向上看791
,它给我留下了一个长串(几百行),看起来像这里的那些:
tcp 0 0 IP_1:3306 IP_2:34109 VERBUNDEN 791/mysqld
tcp 0 0 IP_1:3306 IP_3:32864 VERBUNDEN 791/mysqld
tcp 0 0 IP_1:3306 IP_3:37231 VERBUNDEN 791/mysqld
tcp 0 0 IP_1:3306 IP_2:38727 VERBUNDEN 791/mysqld
tcp 0 0 IP_1:3306 IP_2:36645 VERBUNDEN 791/mysqld
但这告诉我什么?我应该收集哪些更多的信息以获得实际导致太多连接问题的线索?
有关申请的进一步信息:
我们运行代码 - 在我们的数据库上更新,插入和删除相当大的代码 - 在几个服务器上,这些服务器通过分支框架 Gearman 获取这些数据。我们正在运行 MySQL INNODB数据库,我们的 PHP 5.4 和 Zend Framework 驱动的应用程序使用它。操作系统 Linux(Debian)。
答案 0 :(得分:6)
大多数(所有?)线程都位于state of Sleep这一事实让我觉得你的应用程序与数据库有一个开放的连接,但是在数据库请求之间。
您可以使用Cacti与Percona Monitoring Plugins一起监控Threads_running与Threads_connected的趋势,从而确认这一点。前者通常比后者低很多,但如果它的方式平均降低,那么你基本上有空闲的数据库连接不必要地占用资源。
你可以做的一些事情:
迟到连接数据库。 Zend Framework的数据库适配器(我最后检查过)默认情况下直到第一个查询才真正连接。您可以覆盖它并强制它尽早连接,但您应该尽量避免这种情况。
提前断开与数据库的连接。在PHP中,习惯性地只是让资源闲置,因为它们会在请求结束时自动清理。但这意味着当应用程序不需要时,以及其他应用程序请求可能正在等待时,您的应用程序会保留与数据库服务器的连接一段时间。一旦他们获取了他们需要的最后数据,您应该对应用程序进行编码以立即断开与数据库的连接。
最小化连接时间。如果您可以连接到数据库,快速获取给定页面请求所需的所有数据,然后立即断开连接,释放服务器上的连接资源。这可能意味着重构您的PHP代码。无论您需要做什么来分析数据或将其格式化为输出都可以在关闭数据库连接后完成。
请勿进行必要的连接。如果您的应用可以从memcached或APC或类似的缓存中获取所需的数据,那么您的某些页面请求可能根本不需要触摸数据库。
优化查询。另一种可能性是,某些查询长时间运行,并且将开放线程保持在Sleep之外的状态。换句话说,实际执行查询。但是,如果查询的速度始终快于它们可以完成的平均速度,那么往往会堆积很长的连接队列。让您的查询运行得更快。
这样做的方法太多了,不能在这里重述,但你可以在这里开始学习它:
答案 1 :(得分:3)
经过长时间的调试和测试后,我终于找到了导致这些困倦连接的错误,最终导致too many connections
错误。
我发现,我做了一个Zend_Db_Table_Select
操作,比如这个:
// $this->tablename is instance of Zend_Db_Table_Abstract
$select = $this->tablename->select();
$select->where('id = ?', $id);
return $this->tablename->fetchAll($select)->toArray();
Zend让连接打开直到脚本结束 但是因为我使用Gearman意味着我的PHP工作者脚本被用来永远运行,所以脚本永远不会终止,因此这些连接将保持打开状态。 所以最后你有一千个开放但困倦的联系。
那么我们如何关闭这样的东西呢?
我做了一个__destruct()
方法,它只包含:
// both $this->useraddons and $this->db get set up in my __construct()
$this->useraddons->getDefaultAdapter()->closeConnection();
$this->db->closeConnection();
每次我想关闭连接时,我只需要unset($myTableClass)
。