Mysql
 sql >> Datenbank >  >> RDS >> Mysql

Ursachen für MySQL-Fehler 2014 Abfragen können nicht ausgeführt werden, während andere ungepufferte Abfragen aktiv sind

Das MySQL-Client-Protokoll lässt nicht zu, dass mehr als eine Abfrage „in Bearbeitung“ ist. Das heißt, Sie haben eine Abfrage ausgeführt und einige der Ergebnisse abgerufen, aber nicht alle – dann versuchen Sie, eine zweite Abfrage auszuführen. Wenn die erste Abfrage noch Zeilen zurückzugeben hat, erhält die zweite Abfrage einen Fehler.

Clientbibliotheken umgehen dies, indem sie alle abrufen die Zeilen der ersten Abfrage implizit beim ersten Abruf, und nachfolgende Abrufe iterieren einfach über die intern zwischengespeicherten Ergebnisse. Dies gibt ihnen die Möglichkeit, den Cursor zu schließen (soweit es den MySQL-Server betrifft). Dies ist die "gepufferte Abfrage". Dies funktioniert genauso wie die Verwendung von fetchAll(), da in beiden Fällen genügend Speicher im PHP-Client zugewiesen werden muss, um die vollständige Ergebnismenge aufzunehmen.

Der Unterschied besteht darin, dass eine gepufferte Abfrage das Ergebnis in der MySQL-Client-Bibliothek hält, sodass PHP nicht auf die Zeilen zugreifen kann, bis Sie jede Zeile nacheinander mit fetch() abrufen. Während fetchAll() sofort ein PHP-Array mit allen Ergebnissen füllt, sodass Sie auf jede beliebige Zeile zugreifen können.

Der Hauptgrund nicht fetchAll() zu verwenden ist, dass ein Ergebnis möglicherweise zu groß ist, um in Ihr PHP-memory_limit zu passen. Aber es scheint, dass Ihre Abfrageergebnisse sowieso nur eine Zeile haben, also sollte das kein Problem sein.

Sie können closeCursor() verwenden, um ein Ergebnis zu "verwerfen", bevor Sie die letzte Zeile abgerufen haben. Der MySQL-Server wird benachrichtigt, dass er dieses Ergebnis serverseitig verwerfen kann, und Sie können dann eine weitere Abfrage ausführen. Sie sollten Cursor() nicht schließen, bis Sie mit dem Abrufen einer bestimmten Ergebnismenge fertig sind.

Außerdem:Mir ist aufgefallen, dass Sie Ihr $stmt2 immer wieder innerhalb der Schleife ausführen, aber es wird jedes Mal das gleiche Ergebnis zurückgeben. Nach dem Prinzip, schleifeninvarianten Code aus der Schleife herauszubewegen, sollten Sie dies vor dem Starten der Schleife einmal ausgeführt und das Ergebnis in einer PHP-Variablen gespeichert haben. Unabhängig davon, ob Sie gepufferte Abfragen oder fetchAll() verwenden, müssen Sie Ihre Abfragen nicht verschachteln.

Daher würde ich empfehlen, Ihren Code folgendermaßen zu schreiben:

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

Hinweis:Ich habe auch benannte Parameter anstelle von Positionsparametern verwendet, was es einfacher macht, $row als Array von Parameterwerten zu übergeben. Wenn die Schlüssel des Arrays mit den Parameternamen übereinstimmen, können Sie das Array einfach übergeben. In älteren PHP-Versionen mussten Sie den : einfügen Präfix in den Array-Schlüsseln, aber das brauchen Sie nicht mehr.

Sie sollten trotzdem mysqlnd verwenden. Es hat mehr Funktionen, ist speichereffizienter und seine Lizenz ist mit PHP kompatibel.