Ошибка базы данных: [mysqli.mysqli]: пользователь уже имеет более активных подключений 'max_user_connections' - PullRequest
0 голосов
/ 22 апреля 2009

У меня есть сайт, который ежедневно посещает около 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 

Я обновляю страницу пару раз, и теперь она в порядке, но так как у меня не так много пользователей, я подозреваю, что ошибка в моем коде, где мне ее искать?

Thx

Редактировать: это файл модели:

<?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 ]

5 голосов
/ 23 апреля 2009

При каждом обращении к вашему веб-сайту, которое открывает соединение с базой данных, используется одно и то же имя пользователя и пароль базы данных. В настройках вашей базы данных количество подключений для каждого пользователя ограничено, и вы превышаете этот максимум.

Проверьте эту страницу руководства MySQL: http://dev.mysql.com/doc/refman/5.0/en/user-resources.html

Ваш класс модели не так хорош, так как кажется, что он открывает и закрывает соединение с базой данных при каждом отдельном запросе. Это очень плохое использование ресурсов, так как открытие и закрытие соединений обходятся дорого. Я написал бы функцию-деструктор для вашего модельного объекта с именем $ db-> close () и изменил бы getConnection (), чтобы открыть соединение один раз, а затем возвращал его каждый раз после этого. Это означает преобразование класса вашей модели в нестатическое использование, но в базе данных было бы намного проще сделать это.

Как бы то ни было, при подключении и отключении вашего класса возможно, что MySQL создает резервные копии подключений, и они не очищаются достаточно быстро, прежде чем вы достигнете максимального пользовательского лимита.

2 голосов
/ 22 апреля 2009

Посмотрите на ваш код, который обрабатывает ваши соединения с базой данных. Вы используете бассейн? Вы используете одну из сред абстракции базы данных PHP?

Обрабатываете ли вы соединения при каждом доступе к базе данных? Если это так, вы ищете код, который явно не освобождает / закрывает соединения с базой данных. (если вы делаете это таким образом, я бы посоветовал посмотреть на такую ​​статью: http://www.devshed.com/c/a/PHP/Database-Abstraction-With-PHP/)

1 голос
/ 23 апреля 2009

Здесь есть две проблемы; одно усугубляет другое.

@ zombat определил большую проблему: вам не нужно подключаться и отключаться для каждого запроса. Хотя MySQL имеет быстрый цикл установки и демонтажа, он тратит впустую другие ресурсы. Более разумно открыть соединение один раз на этапе настройки кода, а затем повторно использовать соединение для каждого запроса, пока не закончится страница. Я бы предложил использовать переменную экземпляра для объекта mysqli.

(Если у вас есть структура, в которой есть несколько баз данных, и какая из них зависит от объекта, вам нужно усовершенствовать обработчик базы данных, чтобы отслеживать, какие соединения с базой данных у него открыты, чтобы он открывал только те, которые ему нужны. Но это гораздо более сложная тема, которая большинству людей не понадобится.)

Здесь «другие ресурсы» - это соединения MySQL. Если mysqli создает постоянные соединения, он фактически не будет закрывать соединение с MySQL (на самом деле он должен также повторно использовать соединения, чтобы у вас даже не возникало этой проблемы, но я отступаю). Значение MySQL по умолчанию для тайм-аута таких соединений составляет несколько часов, так что вы, вероятно, достигаете этого предела. Если вы видите сотни «спящих» потоков в SHOW PROCESSLIST, то это то, что происходит. Параметр для изменения wait_timeout. И max_connections тоже может быть слишком низким.

Но я рекомендую сначала починить обработчик базы данных.

1 голос
/ 23 апреля 2009

это должно решить твою проблему, но я не проверял это. разница: если getConnection() вызывается в первый раз, соединение устанавливается и сохраняется. В остальное время используется уже установленное соединение.

Я удалил действие в closeConnection, потому что это сделало бы первое изменение бесполезным. хотя было бы лучше удалить вызов closeConnection из execSQL.

обычно (насколько я знаю) соединение с базой данных автоматически закрывается, когда сценарий завершается (до тех пор, пока 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 (...)
}

?>

и ... я бы рекомендовал использовать существующий уровень абстракции доступа к базе данных, чтобы избежать подобных проблем в будущем.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...