2009-04-22 14 views
0

私は毎日のちょうど約100人を取得しますが、ユーザーとしてログインしたときに、私は、このエラーメッセージが表示されましたサイトを持っている:私は、ページの時間のカップルと、今その[OK]をリフレッシュデータベースエラー

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



} 

?> 
+0

ありがとう、私は基本的に$ dbと同じようにする必要がありますか? $ results-> close();を使用して別の関数を作成します。 ? – jcslzr

+0

正直、わかりません。私のコメントは削除されました。しかし、mysqliのドキュメントを見ると、クエリ結果セットがデータベースへのバッファリングされた接続であることを強く意味していることがわかります。 $ db-> close()が接続を終了するように見えますが、クエリのドキュメントはデータベース接続を使用して結果を取得していることを示しています。 – GoingTharn

+0

ありがとう、私はそれを調べます。 – jcslzr

答えて

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 (...) 
} 

?> 

...将来このような問題を避けるために、既存のデータベースアクセス抽象レイヤーを使用することをお勧めします。

+0

ありがとうDudeそれは働いた – jcslzr

2

ルック:これは、モデルファイルです。プールを使っていますか? PHPデータベース抽象化フレームワークの1つを使用していますか?

各データベースアクセスで接続を処理していますか?もしそうなら、あなたは明示的にデータベース接続をリリース/クローズしないコードを探しています。 (あなたはこのようにそれをやっているならば、私はこのような記事を見てお勧めしたい:http://www.devshed.com/c/a/PHP/Database-Abstraction-With-PHP/)あなたはthis doc page --thereを見てみることをお勧めします

1

は、コメント欄でいくつかの有用なヒントがあります。

5

データベース接続を開くWebサイトのすべてのヒットは、同じデータベースのユーザー名とパスワードを使用しています。データベース設定では、ユーザーごとに接続数が制限されており、その最大値を超えています。

このMySQLのマニュアルページをチェックしてください:それは、すべての個々の問い合わせにデータベース接続を開閉しているように見えるようhttp://dev.mysql.com/doc/refman/5.0/en/user-resources.html

あなたのモデルクラスは、その素晴らしいではありません。オープンおよびクローズ接続が高価なので、これはリソースの非常に悪い使用です。 $ db-> close()を呼び出したモデルオブジェクトにデストラクタ関数を記述し、getConnection()を変更して接続を一度開き、それ以降毎回返すようにします。これは、モデルクラスを非静的な使用法に変換することを意味しますが、データベースで行うほうがはるかに簡単です。

あなたのクラスの接続と接続解除で、MySQLが接続をバッ​​クアップしていて、最大限のユーザー制限に達する前に十分に速くクリアされていない可能性があります。

1

ここでは2つの問題があります。 1つは他を悪化させる。

@zombatは、より大きな問題を特定しました。クエリごとに接続および切断する必要はありません。 MySQLはセットアップとティアダウンのサイクルが速いものの、他のリソースを無駄にします。コードの設定ステップで一度接続を開いてから、ページが終了するまでクエリごとに繰り返し接続を使用する方が理にかなっています。私はmysqliオブジェクトのインスタンス変数を使用することをお勧めします。

(データベースに複数のデータベースがあり、オブジェクトに依存する構造の場合は、開いているデータベース接続を追跡して必要なものだけを開くようにデータベースハンドラを強化する必要があります。しかし、これははるかに高度なトピックであり、ほとんどの人が行う必要はありません。)

ここで再生される「その他のリソース」はMySQL接続です。 mysqliが永続的な接続を作成している場合、MySQLへの接続を実際に閉じているわけではありません(実際には接続を再利用する必要がありますので、この問題は発生しません。このような接続をタイムアウトさせるMySQLのデフォルト値は数時間ですので、おそらくその限界に達しています。 SHOW PROCESSLISTに数百の「スリープ」スレッドが表示された場合、これが起こっています。変更するパラメータはwait_timeoutです。 max_connectionsも低すぎる可能性があります。

しかし、まずデータベースハンドラを修正することをお勧めします。

関連する問題