W3docs

Funzione PHP mysqli_poll()

Guida alla funzione PHP mysqli_poll(): sintassi, parametri, valori restituiti e come monitorare connessioni MySQL asincrone con un esempio completo.

La funzione mysqli_poll() consente di attendere su più connessioni MySQL contemporaneamente e di scoprire quali di esse hanno completato l'esecuzione di una query asincrona. È il ponte tra l'avvio di query non bloccanti e la raccolta dei loro risultati senza bloccare l'intero script sulla connessione più lenta.

Cosa fa mysqli_poll()

Quando si esegue una query nel modo normale, PHP si ferma e attende finché MySQL risponde. Con le query asincrone (avviate con il flag MYSQLI_ASYNC), la query viene inviata ma lo script continua l'esecuzione. Il problema diventa: come faccio a sapere quando un risultato è pronto per essere letto? È proprio a questo che risponde mysqli_poll().

Si passa un elenco di connessioni e la funzione blocca l'esecuzione fino a quando almeno una di esse ha un risultato in attesa (o fino allo scadere di un timeout). Poi indica quali connessioni sono pronte e si raccolgono i loro risultati con reap_async_query().

Questo è utile quando occorre eseguire più query indipendenti in parallelo — ad esempio, interrogare due database diversi o eseguire più report lenti contemporaneamente. Invece di pagare il costo di ogni query una dopo l'altra, si avviano tutte e le si lascia eseguire in modo concorrente.

Importante: mysqli_poll() funziona solo con il driver mysqlnd. Non è disponibile con il vecchio driver libmysql. È inoltre solo procedurale — non esiste un metodo orientato agli oggetti $mysqli->poll(); va sempre chiamata come mysqli_poll(...).

Sintassi

mysqli_poll(
    array &$read,
    array &$error,
    array &$reject,
    int $seconds,
    int $microseconds = 0
): int|false

Parametri

ParametroDescrizione
$readElenco di connessioni da verificare per i risultati. Passato per riferimento — al ritorno viene riscritto per contenere solo le connessioni con un risultato pronto.
$errorRiscritto per contenere le connessioni su cui si è verificato un errore.
$rejectRiscritto per contenere le connessioni rifiutate (nessuna query asincrona in attesa su di esse).
$secondsNumero massimo di secondi da attendere.
$microsecondsMicrosecondi aggiuntivi da attendere (facoltativo, predefinito 0).

Valore restituito

Restituisce il numero di connessioni pronte in caso di successo, oppure false in caso di errore. Un valore restituito di 0 significa che il timeout è scaduto prima che qualsiasi connessione diventasse pronta — non è un errore.

Come usare la funzione mysqli_poll()

Il pattern è sempre composto da tre passaggi:

  1. Aprire una connessione per ogni query che si vuole eseguire in parallelo.
  2. Avviare ogni query con il flag MYSQLI_ASYNC in modo che non blocchi.
  3. Eseguire un ciclo, chiamando mysqli_poll() per attendere la connessione che termina per prima, e raccogliere il suo risultato.
<?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();
?>

Anche se la prima query attende 1 secondo e la seconda 2 secondi, l'intero script termina in circa 2 secondi, non 3 — le due query sono state eseguite contemporaneamente. Poiché la query da 1 secondo termina per prima, l'output è:

orders done
reports done

Cosa fa il codice, passo per passo

  • Si aprono due connessioni perché ogni connessione può eseguire solo una query asincrona alla volta.
  • query(..., MYSQLI_ASYNC) invia ogni query e ritorna immediatamente invece di attendere.
  • Prima di ogni chiamata a mysqli_poll() si copia $pending in $read, $error e $reject, perché la funzione riscrive quegli array per riferimento. $read ritorna contenendo solo le connessioni pronte, $error quelle fallite e $reject quelle senza query in attesa.
  • Per ogni connessione pronta si chiama reap_async_query() per raccogliere il set di risultati, poi si rimuove quella connessione da $pending per non interrogarla di nuovo.
  • Il ciclo termina una volta che ogni query è stata raccolta.

Nota: Per carichi di lavoro asincroni complessi, si consiglia di considerare librerie event-loop come ReactPHP o Swoole, che forniscono architetture più robuste rispetto alla creazione manuale di un ciclo di polling.

Funzioni correlate

  • reap_async_query() — raccoglie il risultato di una connessione che mysqli_poll() ha segnalato come pronta.
  • query() — esegue una query (aggiungere MYSQLI_ASYNC per renderla non bloccante).
  • multi_query() — esegue più istruzioni in una sola chiamata su una singola connessione.
  • connect_errno — verifica se un tentativo di connessione è fallito.

Conclusione

mysqli_poll() è l'elemento che rende pratico l'uso di query MySQL parallele in PHP: attende su molte connessioni contemporaneamente e indica quali sono pronte per essere lette. Abbinata a query MYSQLI_ASYNC e reap_async_query(), ricordando che richiede il driver mysqlnd, permette di ridurre il tempo totale di più query indipendenti approssimativamente al tempo della più lenta.

Pratica

Pratica
Quali affermazioni sulla funzione PHP mysqli_poll() sono corrette?
Quali affermazioni sulla funzione PHP mysqli_poll() sono corrette?
Was this page helpful?