W3docs

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|false

Parâmetros

ParâmetroDescrição
$readLista 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.
$errorReescrito para conter conexões em que ocorreu um erro.
$rejectReescrito para conter conexões que foram rejeitadas (sem consulta assíncrona pendente nelas).
$secondsNúmero máximo de segundos para aguardar.
$microsecondsMicrossegundos 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:

  1. Abrir uma conexão por consulta que você deseja executar em paralelo.
  2. Iniciar cada consulta com o sinalizador MYSQLI_ASYNC para que não bloqueie.
  3. 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 done

O 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 $pending em $read, $error e $reject, pois a função reescreve esses arrays por referência. $read volta contendo apenas as conexões prontas, $error as com falha, e $reject qualquer 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 $pending para 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 que mysqli_poll() relatou como pronta.
  • query() — executa uma consulta (adicione MYSQLI_ASYNC para 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.

Prática

Prática
Quais afirmações sobre a função PHP mysqli_poll() estão corretas?
Quais afirmações sobre a função PHP mysqli_poll() estão corretas?
Was this page helpful?