Php 调试休眠的MySQL连接

Php 调试休眠的MySQL连接,php,mysql,linux,performance,zend-framework,Php,Mysql,Linux,Performance,Zend Framework,我想我的应用程序出现了一些问题,这些问题使我们的整个应用程序速度变慢,可能会造成损坏和其他问题。 应用程序问题由许多处于休眠状态的mysql连接引起 显示进程列表输出: | 356058234 | Y | X:39119 | D | Sleep | 1442 | | NULL | | 356058441 | Y | X:39126 | D | Sleep | 1442 | | NULL | | 3560593

我想我的应用程序出现了一些问题,这些问题使我们的整个应用程序速度变慢,可能会造成损坏和其他问题。
应用程序问题由许多处于休眠状态的mysql连接引起

显示进程列表输出:

| 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
但这告诉我什么呢?我应该收集哪些更多的信息来找出导致连接太多问题的线索

有关应用程序的更多信息:
我们在几个服务器上运行代码,这些代码在我们的数据库中更新、插入和删除相当大的数据,这些服务器通过forking FrameworkGearman获取这些数据。我们正在运行一个MySQL-INNODB数据库,它被我们的php5.4Zend框架驱动的应用程序使用。操作系统是Linux(Debian)

大多数(所有?)线程都在一个线程中,这一事实让我认为您的应用程序与数据库有一个开放的连接,但处于数据库请求之间

您可以通过使用来监视与的趋势来确认这一点。前者通常比后者低很多,但如果平均值低,则基本上会有空闲的数据库连接不必要地占用资源

你可以做几件事:

  • 延迟连接到数据库。默认情况下,Zend Framework的数据库适配器(上次选中)在第一次查询之前不会真正连接。您可以覆盖它并强制它提前连接,但应尽量避免这种情况

  • 尽早断开与数据库的连接。在PHP中,通常只保留资源,因为当请求结束时,资源会自动清理。但这意味着,当你的应用程序不需要连接数据库服务器时,以及当其他应用程序请求可能正在等待连接时,你的应用程序会保留与数据库服务器的连接一段时间。你应该对你的应用程序进行编码,一旦它们获取了所需的最后数据,就立即与数据库断开连接

  • 尽量减少连接时间。如果可以连接到数据库,请快速获取给定页面请求所需的所有数据,然后立即断开连接,释放服务器上的连接资源。这可能意味着重构PHP代码。在关闭数据库连接后,可以执行分析数据或格式化数据以供输出所需的任何操作

  • 不要进行不必要的连接。如果你的应用程序可以从或类似的缓存中获取所需的数据,那么你的一些页面请求可能根本不需要接触数据库

  • 优化查询。另一种可能是某些查询是长时间运行的,并且将打开的线程保持在非睡眠状态。换句话说,实际执行一个查询。但是,如果查询的速度始终快于完成查询的平均速度,那么连接的队列就会越来越长。使您的查询运行得更快

    这样做的方法太多,无法在此详述,但您可以从这里开始了解:


经过长时间的调试和测试,我终于找到了导致那些连接不畅的错误,并最终导致
连接过多
错误

我发现,我做了一个
Zend\u Db\u Table\u 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 worker脚本将永远运行,脚本永远不会终止,因此这些连接将作为休眠连接保持打开状态。
因此,最终你有一千个开放但困倦的连接

那么我们如何关闭这样的东西呢? 我为自己制作了一个
\uu destruct()
方法,它只包含:

// both $this->useraddons and $this->db get set up in my __construct()
$this->useraddons->getDefaultAdapter()->closeConnection();
$this->db->closeConnection();

每次我想关闭连接时,我只需要做一个
unset($myTableClass)

很好的回答。我认为58.6个连接/秒也可能表明您的负载非常高,或者您的应用程序管理连接非常糟糕。您的应用程序服务器是否每天处理500万个请求(如果为每个请求创建一个连接,这将是一个近似的连接速率,这在PHP应用程序中可能是典型的)。谢谢您的回答。我可以确认大多数连接都处于休眠状态。而
显示进程列表表示大约433个连接
SELECT*FROM information\u schema.processlist WHERE command!='按id排序的睡眠约50。