【问题标题】:What can cause DB PDO Connection failed: SQLSTATE[08004] [1040] Too many connections什么可能导致 DB PDO 连接失败:SQLSTATE[08004] [1040] 连接过多
【发布时间】:2013-10-27 21:05:38
【问题描述】:

我已经被这个错误困扰了好几天了,我找不到修复它的方法。我已经尝试实现

  • 单例数据库对象
  • 查询后关闭我的连接
  • 尝试持久连接
  • 将最大连接数设置为 250(本地)
  • 设置最大用户连接数 250(本地)

其他人也遇到过这种情况吗?


奇怪的是我的本地服务器上的错误消息是Connection failed: SQLSTATE[08004] [1040],但行仍然是插入并且数据库查询工作。

在生产服务器上,错误消息变为Connection failed: SQLSTATE[42000] [1203] User db_admin already has more than 'max_user_connections' active connections 我知道最大连接数设置为 15,但我咨询了支持人员,他们说我在出现此错误时没有连接。

在我做出所有选择之后,有人可以检查我的代码以确保其中没有可能导致这些错误的错误吗?

class MyPDO extends PDO{

    const DB_HOST='localhost';
    const DB_PORT='3306';
    const DB_NAME='db_name';
    const DB_USER='db_admin';
    const DB_PASS='SECRET';

    public function __construct(){

        parent::__construct('mysql:host='.MyPDO::DB_HOST.';port='.MyPDO::DB_PORT.';dbname='.MyPDO::DB_NAME,
                            MyPDO::DB_USER,MyPDO::DB_PASS);
        try{
                $this->db = new MyPDO();
                $this->db->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_OBJ);
            }catch(PDOException $e){
                //always catching the connection errors
                echo 'Connection failed: ' . $e->getMessage();
            }
    }

    public function query($query){ 
        $args = func_get_args();
        array_shift($args); 
        //check inputs
        var_dump($args);
        $reponse = parent::prepare($query);
        $reponse->execute($args);
        return $reponse;    
    }  
}

这是插入查询

function InsertUserToSql()
    {
        $ret = $this->db->query("INSERT INTO CD_USERS (email,username,password,fname,lname,dob,gender) VALUES 
        (?,?,?,?,?,?,?)",$this->Email,$this->Username,$this->Password,$this->Fname,
        $this->Lname,$this->Birthday,$this->Gender);
        if($ret){
            echo "insert success";
            return $this->db->lastInsertId();
        } 
        $this->db = null;
    }  

【问题讨论】:

    标签: php mysql database pdo


    【解决方案1】:

    不要扩展PDO,事实上,永远不要扩展你不拥有的对象。扩展 PDO 对于最终将使用您的代码的人来说很烦人,这完全没有意义(您要做什么?改进清晰且众所周知的 PDO API?或者创建一个更适合您当前需求的对象 -这意味着:创建一个您将无法再次使用的对象,这违背了 OOP 的意义)? I've been over quite a few reasons why you shouldn't extend from PDO here,可能值得一看。

    你的实际问题:

    不要在自己的构造函数中创建类的新实例!

    MyPDO构造函数中创建一个新的MyPDO会再次调用MyPDO构造函数,这将创建一个MyPDO的新实例,这将再次调用MyPDO构造函数,这将创建一个新的MyPDO 的实例,它将再次调用 MyPDO 构造函数,这将...
    这是工作中的无限递归。

    这样想:如果有人告诉你这个:

    “如果你将右脚移到左脚前面,你必须再次将右脚移到左脚前面”
    然后,那个固执己见的虐待狂会告诉你(在枪口下):
    “现在把你的右脚放在左脚前面”
    您需要多长时间才能完成Grand ecart(或拆分),并且不能再进一步了。这就是您的代码中发生的情况。

    而且,稍微偏离主题,如果您遇到问题,并尝试在 PHP 中使用单例解决它,那么您将引入一个新问题...

    【讨论】:

    • 好吧,做一些食物要点,但我很好奇:“永远不要扩展你不拥有的对象”。此时您将如何定义所有权?因为(1)我喜欢使用经过验证且运行良好的库(2)我错过了功能,所以我基本上可以选择通过扩展装饰器/代理对象来添加代码(当然不是内联,因为它使任何升级都成为一场噩梦)(3)扩展意味着扩展的功能仍然适合函数签名并且可以在该库中使用,代理/装饰意味着它不能,我必须跳过箍。
    • @Wrikken:所有权我的意思是:不要扩展核心对象,因为它们可能在 PHP 的下一个版本中发生变化 + 你没有 direct 访问源。从库扩展很好,如果库是意味着要扩展的(就像框架组件一样)。 PHP 核心对象不是。你说:我想念功能:很好,然后扩展扩展(这就是 PDO 是什么)不会为该扩展添加功能,你可能正在为你的特定数据库 API 添加方法用例。因为它是针对特定应用程序的,所以它属于另一个类,而不是 API 本身
    【解决方案2】:

    您有递归代码:一个实例在$this->db 中创建一个新实例,它在its $this->db 中创建一个新实例,然后又创建另一个实例,依此类推,直到最深的一个抛出一个错误(或者你超出了 PHP 中的最大嵌套深度(不是在 vannilla 中,但某些模块(Zend,xdebug)设置了一个限制),以先到者为准),并且你留下了成功的最大 N 个实例,根据您的代码判断,您可能只使用第二个(如果MyPDO extends PDO,您可以调用$this->query(),在->db 中不需要另一个实例,并使用$this->db->query()

    【讨论】:

    • 哦,所以你的意思是我唯一需要的 $this->db 是当我构造 MyPDO 对象时?
    • 是的。我的意思是,确实从您的 MyPDO 对象中删除整个 ->db 属性。数据库通常没有数据库作为属性,除非您故意设置多个实例来平衡不同的服务器,即使那样也不是递归的。不要忘记将行:$this->db->setAtrribute(PDO::ATTR_DEFAULT_FETCH_MODE,.. 也更改为 $this->setAttribute(..
    猜你喜欢
    • 2018-12-22
    • 1970-01-01
    • 2012-06-29
    • 2019-04-29
    • 1970-01-01
    • 1970-01-01
    • 2015-08-06
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多