Função PHP mysqli_poll()
Aprenda a função PHP mysqli_poll(): sintaxe, parâmetros, valores de retorno e como consultar conexões MySQL assíncronas com um exemplo completo.
A função mysqli_poll() permite aguardar várias conexões MySQL ao mesmo tempo e descobrir quais delas concluíram a execução de uma consulta assíncrona. Ela é a ponte entre disparar consultas não bloqueantes e coletar seus resultados sem bloquear todo o script na conexão mais lenta.
O que mysqli_poll() faz
Quando você executa uma consulta da forma normal, o PHP para e aguarda até o MySQL responder. Com consultas assíncronas (iniciadas com o sinalizador MYSQLI_ASYNC), a consulta é enviada mas seu script continua executando. O problema então é: como saber quando um resultado está pronto para ser lido? É isso que mysqli_poll() responde.
Você passa uma lista de conexões e ela bloqueia até que pelo menos uma delas tenha um resultado aguardando (ou até que um tempo limite expire). Ela então informa quais conexões estão prontas, e você busca seus resultados com reap_async_query().
Isso importa quando você precisa executar várias consultas independentes em paralelo — por exemplo, consultando dois bancos de dados diferentes ou executando vários relatórios lentos ao mesmo tempo. Em vez de pagar o custo de cada consulta uma após a outra, você as dispara todas e as deixa executar de forma concorrente.
Importante: mysqli_poll() só funciona com o driver mysqlnd. Não está disponível com o driver mais antigo libmysql. Também é somente procedural — não existe um método orientado a objetos $mysqli->poll(); você sempre a chama como mysqli_poll(...).
Sintaxe
mysqli_poll(
array &$read,
array &$error,
array &$reject,
int $seconds,
int $microseconds = 0
): int|falseParâmetros
| Parâmetro | Descrição |
|---|---|
$read | Lista de conexões a verificar em busca de resultados. Passado por referência — ao retornar, é reescrito para conter apenas as conexões que têm um resultado pronto. |
$error | Reescrito para conter conexões em que ocorreu um erro. |
$reject | Reescrito para conter conexões que foram rejeitadas (sem consulta assíncrona pendente nelas). |
$seconds | Número máximo de segundos para aguardar. |
$microseconds | Microssegundos adicionais para aguardar (opcional, padrão 0). |
Valor de retorno
Retorna o número de conexões prontas em caso de sucesso, ou false em caso de falha. Um retorno de 0 significa que o tempo limite expirou antes de qualquer conexão ficar pronta — não é um erro.
Como usar a função mysqli_poll()
O padrão é sempre os mesmos três passos:
- Abrir uma conexão por consulta que você deseja executar em paralelo.
- Iniciar cada consulta com o sinalizador
MYSQLI_ASYNCpara que não bloqueie. - Fazer um loop, chamando
mysqli_poll()para aguardar qual conexão terminar primeiro, e coletar seu resultado.
<?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();
?>Mesmo que a primeira consulta durma por 1 segundo e a segunda por 2 segundos, o script inteiro termina em cerca de 2 segundos, não 3 — as duas consultas foram executadas ao mesmo tempo. Como a consulta de 1 segundo termina primeiro, a saída é:
orders done
reports doneO que o código faz, passo a passo
- Abrimos duas conexões porque cada conexão só pode executar uma consulta assíncrona por vez.
query(..., MYSQLI_ASYNC)envia cada consulta e retorna imediatamente em vez de aguardar.- Antes de cada chamada
mysqli_poll(), copiamos$pendingem$read,$errore$reject, pois a função reescreve esses arrays por referência.$readvolta contendo apenas as conexões prontas,$erroras com falha, e$rejectqualquer uma sem consulta pendente. - Para cada conexão pronta, chamamos
reap_async_query()para coletar o conjunto de resultados e, em seguida, removemos essa conexão de$pendingpara não consultá-la novamente. - O loop termina quando todas as consultas foram coletadas.
Nota: Para cargas de trabalho assíncronas complexas, considere bibliotecas de loop de eventos como ReactPHP ou Swoole, que fornecem arquiteturas mais robustas do que criar um loop de poll manualmente.
Funções relacionadas
reap_async_query()— coleta o resultado de uma conexão quemysqli_poll()relatou como pronta.query()— executa uma consulta (adicioneMYSQLI_ASYNCpara torná-la não bloqueante).multi_query()— executa várias instruções em uma única chamada em uma única conexão.connect_errno— verifica se uma tentativa de conexão falhou.
Conclusão
mysqli_poll() é a peça que torna as consultas MySQL paralelas práticas em PHP: ela aguarda em muitas conexões ao mesmo tempo e informa quais estão prontas para leitura. Use-a com consultas MYSQLI_ASYNC e reap_async_query(), lembre-se de que precisa do driver mysqlnd, e você pode reduzir o tempo total de várias consultas independentes para aproximadamente o tempo da mais lenta.