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

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

この MySQL マニュアル ページを確認してください: http://dev.mysql.com/doc/refman/5.0/en/user-resources.html

個々のクエリごとにデータベース接続を開いたり閉じたりしているように見えるため、モデルクラスはそれほど優れていません。接続の開閉にはコストがかかるため、これはリソースの非常に悪い使い方です。$db->close() を呼び出すモデル オブジェクトにデストラクタ関数を記述し、getConnection() を変更して接続を 1 回開き、その後は毎回それを返します。これは、モデル クラスを非静的な使用法に変換することを意味しますが、データベースではこれを行う方がはるかに簡単です。

とにかく、クラスが行っているすべての接続と切断により、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

ここには2つの問題があります。一方が他方を悪化させます。

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

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

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

ただし、最初にデータベースハンドラーを修正することをお勧めします。

于 2009-04-23T02:19:13.383 に答える
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 に答える