PHP mysqli_poll() Function
Learn the PHP mysqli_poll() function: its syntax, parameters, return values, and how to poll asynchronous MySQL connections with a full working example.
The mysqli_poll() function lets you wait on several MySQL connections at once and find out which of them have finished running an asynchronous query. It is the bridge between firing off non-blocking queries and collecting their results without blocking your whole script on the slowest one.
What mysqli_poll() does
When you run a query the normal way, PHP stops and waits until MySQL replies. With asynchronous queries (started with the MYSQLI_ASYNC flag), the query is sent but your script keeps running. The problem then becomes: how do I know when a result is ready to read? That is what mysqli_poll() answers.
You hand it a list of connections and it blocks until at least one of them has a result waiting (or until a timeout elapses). It then tells you which connections are ready, and you fetch their results with reap_async_query().
This matters when you need to run multiple independent queries in parallel — for example, querying two different databases or running several slow reports at once. Instead of paying the cost of each query one after another, you fire them all and let them run concurrently.
Important: mysqli_poll() only works with the mysqlnd driver. It is not available with the older libmysql driver. It is also procedural-only — there is no object-oriented $mysqli->poll() method; you always call it as mysqli_poll(...).
Syntax
mysqli_poll(
array &$read,
array &$error,
array &$reject,
int $seconds,
int $microseconds = 0
): int|falseParameters
| Parameter | Description |
|---|---|
$read | List of connections to check for results. Passed by reference — on return it is rewritten to hold only the connections that have a result ready. |
$error | Rewritten to hold connections on which an error occurred. |
$reject | Rewritten to hold connections that were rejected (no async query pending on them). |
$seconds | Maximum number of seconds to wait. |
$microseconds | Additional microseconds to wait (optional, defaults to 0). |
Return value
Returns the number of ready connections on success, or false on failure. A return of 0 means the timeout elapsed before any connection became ready — it is not an error.
How to use the mysqli_poll() function
The pattern is always the same three steps:
- Open one connection per query you want to run in parallel.
- Start each query with the
MYSQLI_ASYNCflag so it does not block. - Loop, calling
mysqli_poll()to wait for whichever connection finishes next, and reap its result.
<?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();
?>Even though the first query sleeps for 1 second and the second for 2 seconds, the whole script finishes in about 2 seconds, not 3 — the two queries ran at the same time. Because the 1-second query finishes first, the output is:
orders done
reports doneWhat the code does, step by step
- We open two connections because each connection can only run one async query at a time.
query(..., MYSQLI_ASYNC)sends each query and returns immediately instead of waiting.- Before each
mysqli_poll()call we copy$pendinginto$read,$error, and$reject, because the function rewrites those arrays by reference.$readcomes back holding only the ready connections,$errorthe failed ones, and$rejectany with no pending query. - For every ready connection we call
reap_async_query()to collect the result set, then drop that connection from$pendingso we do not poll it again. - The loop ends once every query has been reaped.
Note: For complex asynchronous workloads, consider event-loop libraries like ReactPHP or Swoole, which provide more robust architectures than hand-rolling a poll loop.
Related functions
reap_async_query()— collect the result of a connection thatmysqli_poll()reported as ready.query()— run a query (addMYSQLI_ASYNCto make it non-blocking).multi_query()— run several statements in one call on a single connection.connect_errno— check whether a connection attempt failed.
Conclusion
mysqli_poll() is the piece that makes parallel MySQL queries practical in PHP: it waits on many connections at once and tells you which ones are ready to read. Pair it with MYSQLI_ASYNC queries and reap_async_query(), remember that it needs the mysqlnd driver, and you can cut the total time of several independent queries down to roughly the time of the slowest one.