sql >> データベース >  >> RDS >> Mysql

メッセージの修正方法:SQLSTATE[08004][1040]接続が多すぎます

    Model クラスは新しいDatabaseをインスタンス化します Modelをインスタンス化するたびに、コンストラクター内のオブジェクト (またはそれを拡張するクラス)、あなたは事実上新しいを開いています データベース接続。複数のModelを作成する場合 オブジェクトはそれぞれ独自の独立したデータベース接続を持ちます。これは一般的ではなく、通常は不要であり、リソースを適切に使用していませんが、サーバーで使用可能なすべての接続を使い果たしているため、積極的に有害です。

    たとえば、ループしてModelの配列を作成します オブジェクト:

    // If a loop creates an array of Model objects
    while ($row = $something->fetch()) {
      $models[] = new Model();
    }
    // each object in $models has an independent database connection
    // the number of connections now in use by MySQL is now == count($models)
    

    依存性注入を使用する:

    解決策は、依存性注入と passを使用することです。 Database Model::__construct()へのオブジェクト 独自のインスタンス化を許可するのではなく。

    class Model {
    
      protected $_db;
    
      // Accept Database as a parameter
      public function __construct(Database $db) {
        // Assign the property, do not instantiate a new Database object
        $this->_db = $db;
      }
    }
    

    それを使用するには、制御コード(モデルをインスタンス化するコード)自体がnew Database()を呼び出す必要があります。 1回だけ。次に、制御コードによって作成されたそのオブジェクトを、すべてのモデルのコンストラクターに渡す必要があります。

    // Instantiate one Database
    $db = new Database();
    
    // Pass it to models
    $model = new Model($db);
    

    モデルに別の独立したデータベース接続が実際に必要なユースケースでは、別のデータベース接続を渡すことができます。特に、これはテストに役立ちます 。テストデータベースオブジェクトまたはモックオブジェクトに置き換えることができます。

    // Instantiate one Database
    $db = new Database();
    $another_db = new Database();
    
    // Pass it to models
    $model = new Model($db);
    $another_model = new Model($another_db);
    

    永続的な接続:

    コメントで述べたように、持続的接続を使用することはおそらく解決策ですが、私がお勧めする解決策ではありません 。 PDOは、(すべてのクレデンシャルと同じように)同じクレデンシャルで既存の接続を再利用しようとしますが、スクリプトの実行中に接続がキャッシュされる必要はありません。この方法で行うことにした場合は、属性をDatabaseに渡す必要があります。 コンストラクター。

    try {
      // Set ATTR_PERSISTENT in the constructor:
      parent::__construct(DB_TYPE.':host='.DB_HOST.';dbname='.DB_NAME,DB_USER,DB_PASS, array(PDO::ATTR_PERSISTENT => true));
      $this->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
      $this->setAttribute(PDO::MYSQL_ATTR_INIT_COMMAND, "SET NAMES 'utf8'");
    }
    

    関連するドキュメントは次のとおりです: http://php.net/manual /en/pdo.connections.php#example-950

    シングルトンソリューション:

    シングルトンパターン(これも推奨されません)を使用すると、少なくともこれをモデルコードの検索/置換に減らすことができます。 Database クラスは、それ自体の接続を維持するために静的プロパティを必要とします。次に、モデルはDatabase::getInstance()を呼び出します new Database()の代わりに 接続を取得します。 Database::getInstance()を置き換えるには、モデルコードで検索と置換を行う必要があります。 。

    うまく機能し、実装するのは難しくありませんが、あなたの場合、Database全体を置き換える必要があるため、テストが少し難しくなります。 同じ名前のテストクラスを持つクラス。インスタンスごとにテストクラスを簡単に置き換えることはできません。

    シングルトンパターンをDatabaseに適用します :

    class Database extends PDO{
       // Private $connection property, static
       private static $connection;
    
       // Normally a singleton would necessitate a private constructor
       // but you can't make this private while the PDO 
       // base class exposes it as public
       public function __construct(){
            try {
                parent::__construct(DB_TYPE.':host='.DB_HOST.';dbname='.DB_NAME,DB_USER,DB_PASS);
                $this->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
                $this->setAttribute(PDO::MYSQL_ATTR_INIT_COMMAND, "SET NAMES 'utf8'");
            } catch(PDOException $e){
                Logger::newMessage($e);
                logger::customErrorMsg();
            }
    
        }
    
       // public getInstance() returns existing or creates new connection
       public static function getInstance() {
         // Create the connection if not already created
         if (self::$connection == null) {
            self::$connection = new self();
         } 
         // And return a reference to that connection
         return self::$connection;
       }
    }
    

    これで、Modelのみを変更する必要があります。 Database::getInstance()を使用するコード :

    class Model {
        
      protected $_db;
        
       public function __construct(){
         // Retrieve the database singleton
         $this->_db = Database::getInstance();
       }
    }
    



    1. Access2022を含むMicrosoftAccessの最新ニュースをチェックしてください!

    2. OSXでDjangoを使用してMySQLdbモジュールをロード中にエラーが発生しました

    3. 検索結果をランク付けするためのSQLのヘルプが必要

    4. MySQLでブログ管理用のデータベースを設計するためのガイド