PHP mysqli_poll() Funktion
PHP mysqli_poll() Funktion: Syntax, Parameter, Rückgabewerte und asynchrone MySQL-Verbindungen mit einem vollständigen Beispiel abfragen.
Die Funktion mysqli_poll() ermöglicht es, mehrere MySQL-Verbindungen gleichzeitig zu überwachen und herauszufinden, welche davon eine asynchrone Abfrage abgeschlossen haben. Sie ist die Brücke zwischen dem Absenden nicht-blockierender Abfragen und dem Abrufen ihrer Ergebnisse, ohne das gesamte Skript auf die langsamste Verbindung warten zu lassen.
Was mysqli_poll() macht
Wenn eine Abfrage auf normalem Weg ausgeführt wird, hält PHP an und wartet, bis MySQL antwortet. Bei asynchronen Abfragen (gestartet mit dem Flag MYSQLI_ASYNC) wird die Abfrage gesendet, das Skript läuft aber weiter. Das Problem dabei ist: Wie erkenne ich, wann ein Ergebnis abholbereit ist? Genau das beantwortet mysqli_poll().
Man übergibt ihr eine Liste von Verbindungen, und sie blockiert, bis mindestens eine von ihnen ein Ergebnis bereitstellt (oder bis ein Timeout abläuft). Anschließend teilt sie mit, welche Verbindungen bereit sind, und die Ergebnisse werden mit reap_async_query() abgerufen.
Das ist wichtig, wenn mehrere unabhängige Abfragen parallel ausgeführt werden sollen — zum Beispiel beim Abfragen zweier verschiedener Datenbanken oder beim gleichzeitigen Ausführen mehrerer aufwändiger Berichte. Statt jede Abfrage nacheinander auszuführen, werden alle gleichzeitig gestartet und laufen parallel.
Wichtig: mysqli_poll() funktioniert nur mit dem mysqlnd-Treiber. Mit dem älteren libmysql-Treiber ist sie nicht verfügbar. Außerdem ist sie nur prozedural nutzbar — es gibt keine objektorientierte Methode $mysqli->poll(); sie wird immer als mysqli_poll(...) aufgerufen.
Syntax
mysqli_poll(
array &$read,
array &$error,
array &$reject,
int $seconds,
int $microseconds = 0
): int|falseParameter
| Parameter | Beschreibung |
|---|---|
$read | Liste der zu prüfenden Verbindungen. Per Referenz übergeben — bei der Rückgabe wird sie auf die Verbindungen reduziert, die ein Ergebnis bereitstellen. |
$error | Wird auf Verbindungen reduziert, bei denen ein Fehler aufgetreten ist. |
$reject | Wird auf abgelehnte Verbindungen reduziert (bei denen keine asynchrone Abfrage aussteht). |
$seconds | Maximale Wartezeit in Sekunden. |
$microseconds | Zusätzliche Wartezeit in Mikrosekunden (optional, Standard: 0). |
Rückgabewert
Gibt bei Erfolg die Anzahl der bereiten Verbindungen zurück, oder false bei einem Fehler. Ein Rückgabewert von 0 bedeutet, dass der Timeout abgelaufen ist, bevor eine Verbindung bereit war — das ist kein Fehler.
Verwendung der mysqli_poll() Funktion
Das Muster besteht immer aus denselben drei Schritten:
- Eine Verbindung pro Abfrage öffnen, die parallel ausgeführt werden soll.
- Jede Abfrage mit dem Flag
MYSQLI_ASYNCstarten, damit sie nicht blockiert. - In einer Schleife
mysqli_poll()aufrufen, um auf die nächste fertige Verbindung zu warten, und deren Ergebnis abrufen.
<?php
// Open one connection per parallel query.
$conn1 = new mysqli("localhost", "user", "pass", "shop");
$conn2 = new mysqli("localhost", "user", "pass", "shop");
foreach ([$conn1, $conn2] as $c) {
if ($c->connect_errno) {
exit("Connect failed: " . $c->connect_error);
}
}
// Fire both queries asynchronously — neither call blocks.
$conn1->query("SELECT SLEEP(1), 'orders done' AS msg", MYSQLI_ASYNC);
$conn2->query("SELECT SLEEP(2), 'reports done' AS msg", MYSQLI_ASYNC);
$pending = [$conn1, $conn2];
while (!empty($pending)) {
// Copies that mysqli_poll() will rewrite by reference.
$read = $pending;
$error = $pending;
$reject = $pending;
// Block up to 5 seconds for at least one connection to become ready.
if (mysqli_poll($read, $error, $reject, 5) === false) {
echo "Poll failed.\n";
break;
}
// $read now holds only the connections with a result waiting.
foreach ($read as $conn) {
if ($result = $conn->reap_async_query()) {
$row = $result->fetch_assoc();
echo $row['msg'] . "\n";
$result->free();
} else {
echo "Query error: " . $conn->error . "\n";
}
// Remove this connection from the pending list.
$pending = array_filter($pending, fn($c) => $c !== $conn);
}
}
$conn1->close();
$conn2->close();
?>Obwohl die erste Abfrage 1 Sekunde schläft und die zweite 2 Sekunden, wird das gesamte Skript in etwa 2 Sekunden abgeschlossen — nicht in 3 — da beide Abfragen gleichzeitig liefen. Da die 1-Sekunden-Abfrage zuerst fertig ist, lautet die Ausgabe:
orders done
reports doneWas der Code Schritt für Schritt macht
- Es werden zwei Verbindungen geöffnet, da jede Verbindung nur eine asynchrone Abfrage gleichzeitig ausführen kann.
query(..., MYSQLI_ASYNC)sendet jede Abfrage und kehrt sofort zurück, ohne zu warten.- Vor jedem
mysqli_poll()-Aufruf wird$pendingin$read,$errorund$rejectkopiert, weil die Funktion diese Arrays per Referenz überschreibt.$readenthält danach nur die bereiten Verbindungen,$errordie fehlgeschlagenen und$rejectdie ohne ausstehende Abfrage. - Für jede bereite Verbindung wird
reap_async_query()aufgerufen, um das Ergebnis zu holen, und die Verbindung wird aus$pendingentfernt, damit sie nicht erneut abgefragt wird. - Die Schleife endet, sobald alle Abfragen abgerufen wurden.
Hinweis: Für komplexe asynchrone Arbeitslasten empfehlen sich Event-Loop-Bibliotheken wie ReactPHP oder Swoole, die robustere Architekturen bieten als eine manuell erstellte Poll-Schleife.
Verwandte Funktionen
reap_async_query()— das Ergebnis einer Verbindung abrufen, diemysqli_poll()als bereit gemeldet hat.query()— eine Abfrage ausführen (mitMYSQLI_ASYNCals nicht-blockierende Variante).multi_query()— mehrere Anweisungen in einem Aufruf auf einer einzigen Verbindung ausführen.connect_errno— prüfen, ob ein Verbindungsversuch fehlgeschlagen ist.
Fazit
mysqli_poll() ist das Stück, das parallele MySQL-Abfragen in PHP praktisch macht: Es wartet auf viele Verbindungen gleichzeitig und teilt mit, welche zum Lesen bereit sind. In Kombination mit MYSQLI_ASYNC-Abfragen und reap_async_query() — und dem Wissen, dass der mysqlnd-Treiber benötigt wird — lässt sich die Gesamtzeit mehrerer unabhängiger Abfragen auf etwa die Dauer der langsamsten reduzieren.