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

PDO „Nicht erfasste Ausnahme 'PDOException' .. Abfragen können nicht ausgeführt werden, während andere ungepufferte Abfragen aktiv sind. Erwägen Sie die Verwendung von PDOStatement::fetchAll().“

Sie müssen abrufen, bis ein Zeilenabrufversuch fehlschlägt. Ich weiß, dass Sie möglicherweise nur eine Zeile in der Ergebnismenge haben und denken, dass ein Abruf ausreicht, aber das ist nicht der Fall (wenn Sie ungepufferte Abfragen verwenden). PDO weiß nicht, wie viele Zeilen es gibt, bis es das Ende erreicht, wo es versucht, die nächste Zeile zu holen, aber es scheitert.

Sie haben wahrscheinlich andere Anweisungen, bei denen Sie "nicht vollständig abgerufen haben, bis ein Abruf fehlgeschlagen ist". Ja, ich sehe, dass Sie abrufen, bis der Abruf für eins fehlgeschlagen ist der Aussagen, aber das bedeutet nicht, dass Sie es für alle getan haben.

Zur Verdeutlichung - Wenn Sie eine Abfrage über execute() ausführen, erstellen Sie eine Ergebnismenge, die von der Datenbank in PHP abgerufen werden muss. PDO kann jeweils nur 1 dieser "Ergebnissätze, die gerade abgerufen werden" verarbeiten (pro Verbindung). Sie müssen die Ergebnismenge vollständig bis zum Ende abrufen, bevor Sie mit dem Abrufen einer anderen Ergebnismenge von einem anderen Aufruf von execute() beginnen können.

Wenn Sie "fetch() aufrufen, bis ein fetch() fehlschlägt", wird die Tatsache, dass Sie das Ende der Ergebnisse erreicht haben, intern von PDO vermerkt, wenn dieser letzte Aufruf von fetch() fehlschlägt, weil keine weiteren Ergebnisse vorliegen. PDO ist dann davon überzeugt, dass die Ergebnisse vollständig abgerufen wurden, und es kann alle internen Ressourcen zwischen PHP und der Datenbank bereinigen, die für diese Ergebnismenge eingerichtet wurden, sodass Sie andere Abfragen erstellen/abrufen können.

Es gibt andere Möglichkeiten, PDO "call fetch() until a fetch() fails" zu machen.

  1. Verwenden Sie einfach fetchAll(), das einfach alle Zeilen abruft und somit das Ende der Ergebnismenge erreicht.
  2. oder rufen Sie einfach closeCursor() auf

* Wenn Sie sich die Quelle für closeCursor () ansehen, ruft die Standardimplementierung buchstäblich nur die Zeilen ab und verwirft sie, bis sie das Ende erreicht. Es ist offensichtlich in c geschrieben, aber es tut mehr oder weniger Folgendes:

function closeCursor() {
    while ($row = $stmt->fetch()) {}
    $this->stmtFullyFetched = true;
}

Einige db-Treiber haben möglicherweise eine effizientere Implementierung, bei der sie nicht viele Zeilen abrufen müssen, die niemanden interessieren, aber das ist die Standardmethode von PDO. Jedenfalls...

Normalerweise treten diese Probleme nicht auf, wenn Sie gepufferte Abfragen verwenden. Der Grund dafür ist, dass PDO bei gepufferten Abfragen, direkt nachdem Sie sie ausgeführt haben, die DB-Ergebnisse automatisch vollständig in den PHP-Speicher holt, also den Teil "call fetch() until a fetch() fails" automatisch für Sie erledigt. Wenn Sie fetch() oder fetchAll() später selbst aufrufen, werden Ergebnisse aus dem PHP-Speicher abgerufen, nicht aus der Datenbank. Im Grunde wird die Ergebnismenge also sofort vollständig abgerufen, wenn gepufferte Abfragen verwendet werden, sodass es keine Möglichkeit gibt, mehr als 1 „Ergebnismenge, die gerade abgerufen wird“ gleichzeitig zu haben (da PHP Single-Threading ist, also keine Chance auf 2 Abfragen laufen gleichzeitig).

Angesichts dessen:

$sql = "select * from test.a limit 1";
$stmt = $dbh->prepare($sql);
$stmt->execute(array());

Möglichkeiten, die Ergebnismenge vollständig abzurufen (vorausgesetzt, Sie möchten nur die erste Zeile):

$row = $stmt->fetch();
$stmt->closeCursor();

oder

list($row) = $stmt->fetchAll(); //tricky

oder

$row = $stmt->fetch();
while ($stmt->fetch()) {}