0

我有一个每天只有大约 100 人访问的网站,但以用户身份登录时收到以下错误消息:

Warning: mysqli::mysqli() [mysqli.mysqli]: (42000/1203): User mexautos_Juan already has more than 'max_user_connections' active connections in /home/mexautos/public_html/kiubbo/data/model.php on line 26

Warning: mysqli::query() [mysqli.query]: Couldn't fetch mysqli in /home/mexautos/public_html/kiubbo/data/model.php on line 87
Query failed 

我刷新了几次页面,现在没问题,但是由于我没有那么多用户,我怀疑错误在我的代码中,我应该在哪里寻找它?

谢谢

编辑:这是模型文件:

<?php
/* 

    Model is the base class from which the other
    model classes will be derived. It offers basic
    functionality to access databases

*/ 
require_once($_SERVER['DOCUMENT_ROOT'].'/config.php'); 
require_once(SITE_ROOT.'includes/exceptions.php'); 

class Model {

    private $created;
    private $modified;

    static function getConnection()
    {
        /* 

            Connect to the database and return a
            connection or null on failure

        */

        $db = new mysqli (DB_HOST, DB_USER, DB_PASS, DB_NAME);
        if(!$db) {
            echo mysql_error();
            throw new Exception('Could not connect to database', EX_NO_DATABASE_CONNECTION);
        }

        return $db;

    }

    static function execSQL($query)
    {
    /*
            Execute a SQL query on the database
            passing the tablename and the sql query.
            Returns the resultset
    */


        $db = null;
        $results = null;
        //echo "query is $query";

        try
        {
            $db = Model::getConnection();
            $results = $db->query($query);
            if(!$results) {
                throw new Exception('Query failed', EX_QUERY_FAILED );
            }
        }
        catch(Exception $e)
        {
            /*  errors are handled higher in the
                    object hierarchy
            */

            throw $e;
        }

        Model::closeConnection($db);

        return $results;
    }

    static function execSQl2($query)
    {
    /*
            Execute a SQL query on the database
            passing the tablename and the sql query.
            Returns the LAST_INSERT_ID
    */


        $db = null;
        $lastid = null;
        //echo "query is $query";

        try
        {
            $db = Model::getConnection();
            $results = $db->query($query);
            if(!$results) {
                throw new Exception('Query failed', EX_QUERY_FAILED );
            }
            $lastid = $db->insert_id;
        }
        catch(Exception $e)
        {
            /*  errors are handled higher in the
                    object hierarchy
            */

            throw $e;
        }

        Model::closeConnection($db);

        return $lastid;
    }

    function delete($table, $id, $conditions = '')
    {
        $query = "delete from $table where id = $id";
        try
        {
            $db = Model::getConnection();
            $results = Model::execSQL($query);
            if(!$results){
                throw new Exception('Could not delete this object', EX_DELETE_ERROR);
            }
            return $results->num_rows;
        }

        catch(Exception $e)
        {
            throw $e;
        }
    }

    static function closeConnection($db)
    {
        $db->close();
    }

    function getCreated()
    {
        return $this->created;
    }

    function setCreated($value)
    {
        $this->created = $value;
    }

    function getModified()
    {
        return $this->modified;
    }

    function setModified($value)
    {
        $this->modified = $value;
    }



}

?>
4

4 回答 4

5

在您的网站上打开数据库连接的每一次点击都使用相同的数据库用户名和密码。您的数据库设置限制了每个用户的连接数,并且您正在超过该最大值。

查看这个 MySQL 手册页: http ://dev.mysql.com/doc/refman/5.0/en/user-resources.html

您的模型类不是那么好,因为它似乎在每个单独的查询上打开和关闭数据库连接。这是对资源的非常糟糕的使用,因为打开和关闭连接的成本很高。我会在您的模型对象上编写一个名为 $db->close() 的析构函数,并更改 getConnection() 以打开一次连接,然后每次都返回它。这意味着将您的模型类转换为非静态用法,但在数据库上这样做会容易得多。

无论如何,您的班级正在执行所有连接和断开连接,MySQL 有连接备份,并且在您达到最大用户限制之前它们没有足够快地清除。

于 2009-04-22T20:59:02.373 回答
2

查看处理数据库连接的代码。你在用游泳池吗?您正在使用其中一种 PHP 数据库抽象框架吗?

您是否在每个数据库访问中处理连接?如果是这样,您正在寻找没有明确释放/关闭数据库连接的代码。(如果你这样做,我建议看这样一篇文章:http: //www.devshed.com/c/a/PHP/Database-Abstraction-With-PHP/

于 2009-04-22T14:37:33.507 回答
1

这应该可以解决您的问题,但我没有测试它。区别:如果getConnection()第一次调用,则建立并存储连接。其余时间,使用已经建立的连接。

我删除了 closeConnection 中的操作,因为这会使第一个更改无用。尽管从 execSQL 中删除 closeConnection 调用会更好。

通常(据我所知),当脚本终止时数据库连接会自动关闭(只要 mysqli 不支持持久性)。但最好在所有数据库内容完成后手动调用(工作)closeConnection。

<?php
class Model {

    private $created;
    private $modified;

    private static $db = false;

    static function getConnection()
    {
        /* 

            Connect to the database and return a
            connection or null on failure

        */


        if (self::$db === false) {
            self::$db = new mysqli (DB_HOST, DB_USER, DB_PASS, DB_NAME);
        }

        if(!self::$db) {
            echo mysql_error();
            throw new Exception('Could not connect to database', EX_NO_DATABASE_CONNECTION);
        }

        return self::$db;
    }

    static function closeConnection()
    {
        // self::$db->close();
    }

    // moar functions (...)
}

?>

并且...我建议使用现有的数据库访问抽象层来避免将来出现此类问题。

于 2009-04-22T22:24:16.973 回答
1

这里有两个问题;一个加剧另一个。

@zombat 发现了更大的问题:您不需要为每个查询连接和断开连接。尽管 MySQL 具有快速的设置和拆卸周期,但它会浪费其他资源。在代码的设置步骤中打开一次连接,然后对每个查询重复使用该连接,直到页面结束,这样更有意义。我建议为 mysqli 对象使用实例变量。

(如果您有一个结构,其中有多个数据库并且哪个依赖于对象,那么您需要增强您的数据库处理程序以跟踪它打开了哪些数据库连接,因此它只打开它需要的那些。但这是一个大多数人不需要做的更高级的主题。)

这里出现的“其他资源”是 MySQL 连接。如果 mysqli 正在创建持久连接,它实际上不会关闭与 MySQL 的连接(事实上,它还应该重新使用连接,这样你甚至不会遇到这个问题,但我离题了)。MySQL 超时此类连接的默认值为几个小时,因此您可能会遇到该限制。如果您看到数百个“睡眠”线程,SHOW PROCESSLIST那么这就是正在发生的事情。要更改的参数是wait_timeout。也max_connections可能太低了。

但我建议您先修复您的数据库处理程序。

于 2009-04-23T02:19:13.383 回答