SQLSTATE[HY000] [1040] 连接过多。

8
有时候当我打开错误日志文件时,会看到这个错误:
[14-Jun-2014 19:09:55 UTC] PHP致命错误:未捕获异常 'PDOException',信息为“SQLSTATE [HY000] [1040]连接过多”位于/home/root/products/db.php的第2行
堆栈跟踪:/home/root/products/db.php(2):PDO->__construct('mysql:host=loca...', 'database', 'password')
/home/root/products/by-brand.php(2):include_once('/home/root/...')
在/home/root/products/db.php上抛出{main}中的第2行。
[14-Jun-2014 19:15:11 UTC] PHP致命错误:未捕获异常 'PDOException',信息为“SQLSTATE [42000]:语法错误或访问冲突:1286未知存储引擎InnoDB”位于/home/root/products/detail.php的第8行。
堆栈跟踪:/home/root/products/name.php(8):PDO->prepare('select * from p...')
在/home/root/products/name.php上抛出{main}中的第8行。
我试图通过使用 $db=null; 来关闭每个脚本来解决此问题,但似乎不起作用。
我联系了服务提供商。他们说一切正常。你需要在最后检查错误。我只有很少的用户。
为什么有时会出现这个错误?
我的主机是无限的:无限的磁盘空间、无限的带宽,但我仍然遇到这个错误。我不知道该怎么解决这个问题。我希望能让我的网站更大,但这些错误让我很困惑。
我的db.php文件包含以下代码。你能检查一下是否没问题吗?也许这是造成问题的原因。
db.php
$db = new PDO('mysql:host=localhost;dbname=mobiles;charset=utf8', 'root', '**somePassword**');
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$db->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);

确保您的应用程序中没有多个PDO对象实例,您只需要一个。 - Blank EDjok
@BlankEDjok 你的意思是我不需要在所有脚本中使用相同的配置文件吗?还是什么?请解释一下,因为我对pdo::还很陌生。 - developer
假设您在一个文件中有您的数据库连接,比如dbconfig.php,您只需要在需要数据库连接的页面上包含一次即可。 - Blank EDjok
2
“无限磁盘空间”是一个谎言。不要使用撒谎的主机。 - Niet the Dark Absol
@Niet 我的Godaddy服务器确实拥有无限的磁盘空间,尽管磁盘空间本身是有限的,但我认为他们始终在扩展存储容量。 - Blank EDjok
您的主机可能没有限制您的磁盘使用,但还有许多其他因素会影响。 - Lightness Races in Orbit
3个回答

12
这是数据库配置的限制。如果您有权限编辑数据库服务的配置文件,则可以更改max_connections值。
请参阅: http://dev.mysql.com/doc/refman/5.5/en/too-many-connections.html 您可以尝试运行此SQL查询(请注意这个值!)
SET GLOBAL max_connections = 512;

获取所有变量的当前值,可以使用以下方法:

SHOW VARIABLES;

或(针对特定变量):
SHOW GLOBAL VARIABLES LIKE '%max_connections%'

顺便提一下,当您不需要PDO object时,请将其设置为null。这将关闭与数据库的连接,并使PHP在脚本完成前关闭活动连接,无需等待。 (哦,您已经做到了,抱歉,我不会编辑删除它。把它当作一个提示)

7
在内存较低或资源较少的情况下,首先要确定根本原因
这个问题出现在你的开发系统中吗?还是出现在你的生产系统中?
如果在开发系统中看到,很可能是一个严重的技术错误。如果在生产系统中看到,问题可能是由于系统限制引起的(不一定是系统超载)。
大多数服务器应用程序为固定数量的传入连接分配了固定数量的RAM(由于技术优势)。
与大多数其他网络服务器应用程序一样,MySQL也分配了固定数量的连接。每次客户端连接时,连接池中的一个插槽会被分配。每次客户端断开连接时,一个插槽会被标记为空闲
虽然您可以扩大预分配的连接池,但要小心操作。您的系统管理员(希望如此)已经明智地选择了连接池的大小。
如果连接池过大,您的应用程序或整个服务器可能会变得无响应:每个计算环境只能处理一定数量的请求。该数字取决于每个请求的平均成本/成本分布。
That said, collect system load and connection amount data over time. 
Figure out, at which situations the error message gets written.

一旦你了解了,你可能会更改MySQL的max_connections设置。

PHP和MySQL

赋值$db = null是可以的,正如这里所解释的。

关于你的问题场景,磁盘空间和带宽很可能并不相关。

通常情况下,你可以准备一个符合单例模式的类,该类提供与数据库服务器通信的唯一接口。其他模式也可能适用。

所有其他脚本应该使用require_once来引用这个类的文件,并使用这个类做所有与数据库相关的事情。

如果正确实现和调用,单例类会使用每个请求处理一个单一的MySQL连接

设置连接数的正确位置是在my.cnf中,通常可以在/etc/目录下找到。在那里,你可以设置一个像这样的值:

[mysqld]
set-variable=max_connections=250

如果出现问题,SHOW processlist 可能会有所帮助。它提供了所有活动连接的详细信息:

enter image description here

在处理 PDOException 的顶层 catch 块中,您可以将 SHOW processlist 的结果保存在日志文件中以供以后分析。但请确保每个时间单位内此类日志条目的数量有限,以免淹没您的日志文件。

请注意,MySQL 允许一个用户连接的客户端连接比 max_connections 多一个,该用户拥有 SUPER 权限

您可以使用这样的用户来收集进程列表信息。或者,在出现 PDOException 时,您可以延迟应用程序一段时间并尝试重新连接,然后保存进程列表。

无限磁盘空间

类似于无限磁盘空间不存在:由于生产的HDD和SSD数量是有限的,这是一个简单的事实;-)

虽然您的提供商没有设置限制,但存在技术限制-这很可能在您的情况下并不重要

实际上,还有另一个限制:编写并运行一个分配越来越多磁盘空间的应用程序。在短时间内,您的提供商将终止您的合同......


7

你的连接代码没有问题。

共享主机上,“无限制”意味着其他用户在资源使用方面没有限制。这意味着他们可以消耗整个资源池,而你的消耗保持适度。

正如评论中告诉你的那样,不要使用这个主机。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接