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

MySQLエラー2014の原因他のバッファリングされていないクエリがアクティブな間はクエリを実行できません

    MySQLクライアントプロトコルでは、複数のクエリを「進行中」にすることはできません。つまり、クエリを実行し、結果の一部をフェッチしましたが、すべてではありません。次に、2番目のクエリを実行しようとします。最初のクエリにまだ返される行がある場合、2番目のクエリはエラーになります。

    クライアントライブラリは、すべてをフェッチすることでこれを回避します 最初のクエリの行は、最初のフェッチ時に暗黙的に実行され、その後のフェッチは、内部にキャッシュされた結果を単純に繰り返し処理します。これにより、カーソルを閉じる機会が与えられます(MySQLサーバーに関する限り)。これが「バッファリングされたクエリ」です。これは、fetchAll()を使用する場合と同じように機能します。どちらの場合も、完全な結果セットを保持するためにPHPクライアントに十分なメモリを割り当てる必要があります。

    違いは、バッファリングされたクエリが結果をMySQLクライアントライブラリに保持するため、各行を順番にfetch()するまで、PHPは行にアクセスできないことです。一方、fetchAll()は、すべての結果のPHP配列にすぐにデータを入力し、任意のランダムな行にアクセスできるようにします。

    しない主な理由 fetchAll()を使用すると、結果が大きすぎてPHPのmemory_limitに収まらない可能性があります。ただし、クエリ結果にはとにかく1行しかないように見えるので、問題はないはずです。

    最後の行をフェッチする前に、closeCursor()を使用して結果を「破棄」することができます。 MySQLサーバーは、サーバー側でその結果を破棄できるという通知を受け取り、別のクエリを実行できます。特定の結果セットのフェッチが完了するまで、Cursor()を閉じないでください。

    また、ループ内で$ stmt2を何度も実行していることに気付きましたが、毎回同じ結果が返されます。ループ不変コードをループから移動するという原則に基づいて、ループを開始する前にこれを1回実行し、結果をPHP変数に保存する必要があります。したがって、バッファリングされたクエリまたはfetchAll()の使用に関係なく、クエリをネストする必要はありません。

    したがって、次のようにコードを記述することをお勧めします:

    $sql ='SELECT temp_id FROM temp1';
    $stmt2 = db::db()->prepare($sql);
    $stmt2->execute();
    $rs2 = $stmt2->fetchAll(PDO::FETCH_ASSOC);
    $stmt2->closeCursor();
    
    $sql='SELECT COUNT(*) AS valid FROM cities_has_zipcodes 
          WHERE cities_id=:cities_id AND zipcodes_id=:zipcodes_id';
    $stmt1 = db::db()->prepare($sql);
    
    foreach($data AS $row)
    {
        try
        {
            $stmt1->execute($row);
            $rs1 = $stmt1->fetchAll(PDO::FETCH_ASSOC);
            $stmt1->closeCursor();
            syslog(LOG_INFO,'$rs1: '.print_r($rs1[0],1).' '.rand());
            syslog(LOG_INFO,'$rs2: '.print_r($rs2[0],1).' '.rand());
        }
        catch(PDOException $e){echo(sql_error($e));}            
    }
    

    注:位置パラメーターの代わりに名前付きパラメーターも使用しました。これにより、パラメーター値の配列として$rowを渡すのが簡単になります。配列のキーがパラメーター名と一致する場合は、配列を渡すだけです。古いバージョンのPHPでは、:を含める必要がありました。 配列キーのプレフィックスですが、もう必要ありません。

    とにかくmysqlndを使用する必要があります。より多くの機能があり、メモリ効率が高く、ライセンスはPHPと互換性があります。



    1. PHPを使用する場合のMySQLとMySQLi

    2. Oracleの関数を自動シーケンスでコンマ区切りの値に分割

    3. Oracleのプラス(+)サインインを使用した左結合と右結合

    4. OracleAppsR12でSSLまたはTLSを有効にする