reap_async_query
Erfahren Sie, wie mysqli_reap_async_query() ein asynchrones MySQLi-Abfrageergebnis in PHP abruft, mit einem parallelen Abfragebeispiel.
Einführung
mysqli_reap_async_query() ruft das Ergebnis einer Abfrage ab, die asynchron mit der MySQLi-Erweiterung gestartet wurde. Eine asynchrone Abfrage wird gesendet, ohne auf den Abschluss durch den Server zu warten — das PHP-Skript läuft weiter, und das Ergebnis wird später abgeholt, sobald der Server signalisiert, dass es bereit ist.
Dies ist das fehlende Glied im asynchronen Workflow von MySQLi. Allein ist mysqli_reap_async_query() nicht sinnvoll nutzbar: Es ergibt nur als letzter Schritt eines dreiteiligen Musters Sinn, bestehend aus mysqli_query(..., MYSQLI_ASYNC) (oder mysqli_send_query()), mysqli_poll() und mysqli_reap_async_query(). Diese Seite erklärt, wie diese Teile zusammenpassen, zeigt ein vollständiges ausführbares Beispiel und listet die häufigsten Fallstricke auf.
Voraussetzung: Asynchrone Abfragen funktionieren nur mit dem mysqlnd-Treiber (dem standardmäßigen nativen Treiber in modernen PHP-Builds). Sie sind nicht verfügbar, wenn MySQLi gegen den älteren
libmysqlclientkompiliert wurde.
Der Lebenszyklus einer asynchronen Abfrage
Eine einzelne asynchrone Abfrage durchläuft drei Phasen:
- Senden — Abfrage mit dem
MYSQLI_ASYNC-Flag starten.mysqli_query($conn, $sql, MYSQLI_RESULT, MYSQLI_ASYNC)(oder die Kurzformmysqli_send_query()) kehrt sofort zurück, ohne auf Ergebnisse zu warten. - Polling —
mysqli_poll()aufrufen, um zu warten, bis eine oder mehrere Verbindungen ein Ergebnis bereit haben. Hier wird blockiert (mit einem selbst kontrollierten Timeout), anstatt bei der Abfrage selbst zu blockieren. - Reaping — Sobald das Polling meldet, dass eine Verbindung bereit ist,
mysqli_reap_async_query($conn)aufrufen, um dasmysqli_resultfür diese Verbindung abzuholen.
Der entscheidende Vorteil liegt im Poll-Schritt. Sie können mehrere Verbindungen in einen einzigen mysqli_poll()-Aufruf legen und alle Abfragen gleichzeitig auf dem Server ausführen lassen. Die Gesamtwartezeit entspricht dann etwa der Dauer der langsamsten Abfrage, nicht der Summe aller Abfragen.
mysqli_poll(): der Schritt, den man nicht überspringen kann
Ein häufiger Fehler ist, mysqli_reap_async_query() direkt nach dem Senden einer Abfrage aufzurufen. Wenn das Ergebnis noch nicht bereit ist, gibt das Reaping false zurück und setzt einen Fehler — es wartet nicht. mysqli_poll() ist die Funktion, die wartet.
mysqli_poll() nimmt Arrays von Verbindungen per Referenz und einen Timeout entgegen:
mysqli_poll($read, $error, $reject, $sec, $usec);$read— ein Array der zu überwachenden Verbindungen. Nach dem Aufruf wird es auf die Verbindungen reduziert, die ein Ergebnis bereithalten.$error/$reject— empfangen Verbindungen mit Protokollfehlern oder abgelehnten Anfragen.$sec/$usec— wie lange gewartet werden soll, in Sekunden und Mikrosekunden.
Die Funktion gibt die Anzahl der bereiten Verbindungen zurück (0 bei Timeout, false bei Fehler).
Vollständiges Beispiel: zwei Abfragen parallel ausführen
Das folgende Beispiel öffnet zwei Verbindungen, sendet auf jeder eine asynchrone Abfrage, pollt bis Ergebnisse vorliegen, und holt jede ab. Ersetzen Sie die Zugangsdaten und das SQL durch Ihre eigenen.
<?php
// One connection per concurrent query.
$conn1 = mysqli_connect("localhost", "user", "password", "shop");
$conn2 = mysqli_connect("localhost", "user", "password", "shop");
// 1. Send both queries asynchronously — neither call blocks.
mysqli_query($conn1, "SELECT COUNT(*) AS n FROM orders", MYSQLI_STORE_RESULT, MYSQLI_ASYNC);
mysqli_query($conn2, "SELECT COUNT(*) AS n FROM customers", MYSQLI_STORE_RESULT, MYSQLI_ASYNC);
$links = [$conn1, $conn2];
$pending = count($links);
// 2. Poll until every connection has reported back.
while ($pending > 0) {
$read = $error = $reject = $links;
// Wait up to 1 second for any connection to become ready.
if (!mysqli_poll($read, $error, $reject, 1)) {
continue; // timeout — nothing ready yet, loop again
}
// 3. Reap each ready connection.
foreach ($read as $link) {
$result = mysqli_reap_async_query($link);
if ($result) {
$row = mysqli_fetch_assoc($result);
echo "Count: " . $row["n"] . "\n";
mysqli_free_result($result);
} else {
echo "Query error: " . mysqli_error($link) . "\n";
}
$pending--;
}
}
?>Jede Verbindung kann jeweils nur eine asynchrone Abfrage gleichzeitig ausführen — deshalb verwendet das Beispiel eine separate Verbindung pro Abfrage. Verwenden Sie eine Verbindung für eine neue asynchrone Abfrage erst wieder, nachdem Sie das vorherige Ergebnis abgeholt haben.
Schritt-für-Schritt-Zusammenfassung
- Öffnen Sie eine Verbindung pro Abfrage, die parallel ausgeführt werden soll (
mysqli_connect()). - Starten Sie jede Abfrage mit dem
MYSQLI_ASYNC-Flag, damit der Aufruf sofort zurückkehrt. - Fassen Sie die Verbindungen in einem Array zusammen und übergeben Sie es mit einem Timeout an
mysqli_poll(). - Rufen Sie für jede Verbindung, die
mysqli_poll()als bereit meldet,mysqli_reap_async_query()auf. - Verarbeiten Sie das zurückgegebene
mysqli_resultund geben Sie es mitmysqli_free_result()frei.
Rückgabewerte und Fehlerbehandlung
mysqli_reap_async_query() gibt zurück:
- Ein
mysqli_result-Objekt für Abfragen, die ein Ergebnis-Set liefern (z. B.SELECT). truefür Abfragen, die keine Zeilen zurückgeben (INSERT,UPDATE,DELETE), wenn sie erfolgreich sind.falsebei einem Fehler oder wenn die Funktion aufgerufen wird, bevor das Ergebnis bereit ist — in diesem Fallmysqli_error()prüfen.
Führen Sie den Reap-Schritt immer nach mysqli_poll() durch. Eine Verbindung abzurufen, die noch nicht bereit ist, ist die häufigste Ursache für mysteriöse false-Rückgaben.
Anwendungsfälle für nicht-blockierende MySQLi-Abfragen
Nicht-blockierende MySQLi-Abfragen sind nützlich für PHP-Entwickler, die mehrere Abfragen parallel ausführen oder lang laufende Abfragen starten möchten, ohne andere Code-Ausführung zu blockieren. Hier sind einige praktische Anwendungsfälle:
1. Parallele Abfrageausführung
Entwickler können nicht-blockierende MySQLi-Abfragen nutzen, um mehrere unabhängige Abfragen parallel auszuführen. Indem jede Abfrage mit mysqli_send_query() gesendet und andere Logik dazwischengeschaltet wird, können Anwendungen die Gesamtwartezeit reduzieren, wenn Daten aus mehreren Tabellen oder Diensten abgerufen werden.
2. Lang laufende Abfragen
Lang laufende Abfragen können asynchron initiiert werden, sodass das PHP-Skript in der Zwischenzeit andere Aufgaben erledigen kann, wie Logging, UI-Aktualisierungen oder die Verarbeitung von Benutzereingaben, während die Datenbank die Operation abschließt.
3. Echtzeit-Anwendungen
Anwendungen, die häufiges Daten-Polling oder Echtzeit-Aktualisierungen erfordern, können Abfragen starten, ohne den Hauptausführungs-Thread einzufrieren. Dies ist besonders nützlich für CLI-basierte Monitoring-Tools oder leichtgewichtige Web-Endpunkte, die schnell antworten müssen.
4. Asynchrone Datenverarbeitung
Entwickler können aufwändige Datenabruf-Aufgaben im Hintergrund auslagern, während das Hauptskript andere Datenströme verarbeitet, was den Gesamtdurchsatz bei Batch-Verarbeitung oder ETL-Workflows verbessert.
Vorteile nicht-blockierender MySQLi-Abfragen
Nicht-blockierende MySQLi-Abfragen bieten PHP-Entwicklern mehrere Vorteile:
1. Verbesserte Performance
Durch die asynchrone Ausführung von Abfragen wird die weitere Code-Ausführung nicht blockiert, was zu einer schnelleren Anwendungsleistung führt. Dies ist besonders vorteilhaft für Anwendungen, die Daten aus mehreren Quellen aggregieren oder Anfragen mit hoher Parallelität verarbeiten.
2. Bessere Ressourcennutzung
Nicht-blockierende Ausführung ermöglicht es dem PHP-Prozess, reaktionsfähig zu bleiben, während er auf Datenbankoperationen wartet, was Leerlaufzeiten reduziert und die Serverressourcennutzung verbessert.
3. Vereinfachtes Management von Hintergrundaufgaben
Entwickler können mehrere Datenbankoperationen verketten, ohne Callbacks zu verschachteln oder komplexe Zustandsmaschinen zu bauen, was den Code für Standard-Prozeduralskripte in PHP leichter lesbar und wartbar macht.
Fazit
mysqli_reap_async_query() ist der letzte Schritt im asynchronen Abfrage-Workflow von MySQLi: Sie starten eine Abfrage mit dem MYSQLI_ASYNC-Flag, warten mit mysqli_poll() darauf, und holen dann das Ergebnis ab. Zusammen eingesetzt ermöglichen diese Funktionen einem PHP-Skript, mehrere Abfragen gegen MySQL parallel auszuführen und die Ergebnisse abzuholen, sobald sie fertig sind, anstatt auf jede einzeln zu warten. Der größte Gewinn ergibt sich, wenn mehrere unabhängige Abfragen vorhanden sind — die Gesamtwartezeit sinkt auf etwa die langsamste Abfrage statt auf die Summe aller. Denken Sie an die zwei Regeln, die dies zuverlässig machen: eine asynchrone Abfrage pro Verbindung, und niemals reapen, bevor mysqli_poll() meldet, dass die Verbindung bereit ist.
Verwandte Themen
- mysqli_poll — auf eine oder mehrere asynchrone Verbindungen warten, bis sie bereit sind.
- mysqli_multi_query — mehrere Anweisungen in einem einzigen Aufruf ausführen.
- mysqli_query — die standardmäßige (synchrone) Abfragefunktion.
- mysqli_connect — die Verbindungen öffnen, auf denen Abfragen ausgeführt werden.
- PHP MySQLi — Übersicht über die MySQLi-Erweiterung.