2009-04-22 3 views
0

У меня есть сайт, который получает всего около 100 человек каждый день, но я получил сообщение об ошибке при входе в систему как пользователь:Database Error

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

Edit: это модель файла:

<?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; 
    } 



} 

?> 
+0

Спасибо, так что я должен делать то же самое, что и с $ db? создать другую функцию с помощью: $ results-> close(); ? – jcslzr

+0

Честно говоря, я не уверен. Я удалил свой комментарий, потому что это что-то вроде моей глубины. Но если вы просмотрите документацию для mysqli, вы заметите, что это сильно означает, что набор результатов запроса - это буферизованное соединение с базой данных. Хотя кажется, что $ db-> close() завершит соединение, в документации для запроса указывается, что он использует соединение с базой данных для получения результатов. – GoingTharn

+0

Спасибо, я посмотрю. – jcslzr

ответ

1

это должно исправить вашу проблему, но я не тестировал ее. разница: если 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 (...) 
} 

?> 

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

+0

Спасибо, Dude это сработало – jcslzr

2

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

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

1

Вы можете захотеть взглянуть на this doc page ли некое некоторые полезные советы в комментариях.

5

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

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

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

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

1

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

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

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

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

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