reap_async_query
Scopri come mysqli_reap_async_query() recupera il risultato di una query asincrona MySQLi in PHP, con un esempio di query parallele tramite mysqli_poll.
Introduzione
mysqli_reap_async_query() recupera il risultato di una query avviata in modo asincrono con l'estensione MySQLi. Una query asincrona è quella che si avvia senza attendere che il server finisca — lo script PHP continua a girare e si raccoglie il risultato in seguito, una volta che il server segnala di essere pronto.
Questo è il tassello mancante del flusso di lavoro asincrono di MySQLi. Da sola, mysqli_reap_async_query() non serve a nulla: ha senso solo come passo finale di un pattern in tre parti composto da mysqli_query(..., MYSQLI_ASYNC) (o mysqli_send_query()), mysqli_poll() e mysqli_reap_async_query(). Questa pagina spiega come questi pezzi si incastrano, mostra un esempio completo eseguibile ed elenca le insidie più comuni.
Requisito: le query asincrone funzionano solo con il driver mysqlnd (il driver nativo predefinito nelle build moderne di PHP). Non sono disponibili quando MySQLi è compilato contro il vecchio
libmysqlclient.
Il ciclo di vita di una query asincrona
Una singola query asincrona attraversa tre fasi:
- Invio — avvia la query con il flag
MYSQLI_ASYNC.mysqli_query($conn, $sql, MYSQLI_RESULT, MYSQLI_ASYNC)(o la forma abbreviatamysqli_send_query()) ritorna immediatamente senza attendere i risultati. - Poll — chiama
mysqli_poll()per attendere che una o più connessioni abbiano un risultato pronto. Qui avviene il blocco (con un timeout che controlli tu), anziché bloccare sulla query stessa. - Reap — una volta che il polling segnala che una connessione è pronta, chiama
mysqli_reap_async_query($conn)per recuperare ilmysqli_resultdi quella connessione.
Il motivo per cui questo è importante è la fase di poll. Puoi inserire più connessioni in una singola chiamata a mysqli_poll() e far girare tutte le loro query sul server contemporaneamente. L'attesa totale diventa approssimativamente il tempo della query più lenta, non la somma di tutte.
mysqli_poll(): la parte che non puoi saltare
Un errore comune è chiamare mysqli_reap_async_query() direttamente dopo aver inviato una query. Se il risultato non è ancora pronto, il reap restituisce false e imposta un errore — non aspetta. mysqli_poll() è la funzione che aspetta.
mysqli_poll() accetta array di connessioni passati per riferimento e un timeout:
mysqli_poll($read, $error, $reject, $sec, $usec);$read— un array delle connessioni che vuoi monitorare. Dopo la chiamata, viene ridotto alle sole connessioni che hanno un risultato in attesa.$error/$reject— ricevono le connessioni con errori di protocollo o richieste rifiutate.$sec/$usec— quanto aspettare, in secondi e microsecondi.
Restituisce il numero di connessioni pronte (0 in caso di timeout, false in caso di errore).
Esempio completo: eseguire due query in parallelo
L'esempio seguente apre due connessioni, avvia una query asincrona su ciascuna, fa polling finché i risultati arrivano e li raccoglie. Sostituisci le credenziali e l'SQL con i tuoi.
<?php
// One connection per concurrent query.
$conn1 = mysqli_connect("localhost", "user", "password", "shop");
$conn2 = mysqli_connect("localhost", "user", "password", "shop");
// 1. Send both queries asynchronously — neither call blocks.
mysqli_query($conn1, "SELECT COUNT(*) AS n FROM orders", MYSQLI_STORE_RESULT, MYSQLI_ASYNC);
mysqli_query($conn2, "SELECT COUNT(*) AS n FROM customers", MYSQLI_STORE_RESULT, MYSQLI_ASYNC);
$links = [$conn1, $conn2];
$pending = count($links);
// 2. Poll until every connection has reported back.
while ($pending > 0) {
$read = $error = $reject = $links;
// Wait up to 1 second for any connection to become ready.
if (!mysqli_poll($read, $error, $reject, 1)) {
continue; // timeout — nothing ready yet, loop again
}
// 3. Reap each ready connection.
foreach ($read as $link) {
$result = mysqli_reap_async_query($link);
if ($result) {
$row = mysqli_fetch_assoc($result);
echo "Count: " . $row["n"] . "\n";
mysqli_free_result($result);
} else {
echo "Query error: " . mysqli_error($link) . "\n";
}
$pending--;
}
}
?>Ogni connessione può eseguire solo una query asincrona alla volta — ecco perché l'esempio usa una connessione separata per ogni query. Riutilizza una connessione per una nuova query asincrona solo dopo aver raccolto il risultato precedente.
Riepilogo passo per passo
- Apri una connessione per ogni query che vuoi eseguire in simultanea (
mysqli_connect()). - Avvia ogni query con il flag
MYSQLI_ASYNCin modo che la chiamata ritorni immediatamente. - Raccogli le connessioni in un array e passalo a
mysqli_poll()con un timeout. - Per ogni connessione che
mysqli_poll()segnala come pronta, chiamamysqli_reap_async_query(). - Elabora il
mysqli_resultrestituito, poi liberalo conmysqli_free_result().
Valori restituiti e gestione degli errori
mysqli_reap_async_query() restituisce:
- Un oggetto
mysqli_resultper le query che producono un set di risultati (es.SELECT). trueper le query che non restituiscono righe (INSERT,UPDATE,DELETE) quando hanno successo.falsein caso di errore, oppure quando viene chiamata prima che il risultato sia pronto — controllamysqli_error()in quel caso.
Subordina sempre il reap a mysqli_poll(). Raccogliere il risultato di una connessione non ancora pronta è la fonte più comune di false misteriosi.
Casi d'uso per le query non bloccanti di MySQLi
Le query non bloccanti di MySQLi sono utili per gli sviluppatori PHP che hanno bisogno di eseguire più query in parallelo o di eseguire query a lungo termine senza bloccare l'esecuzione di altro codice. Ecco alcuni casi d'uso pratici per questo approccio:
1. Esecuzione di query in parallelo
Gli sviluppatori possono usare le query non bloccanti di MySQLi per eseguire più query indipendenti in parallelo. Inviando ogni query con mysqli_send_query() e alternando altra logica, le applicazioni possono ridurre i tempi di attesa complessivi durante il recupero dati da più tabelle o servizi.
2. Query a lungo termine
Le query a lungo termine possono essere avviate in modo asincrono in modo che lo script PHP possa gestire altri compiti, come la registrazione, gli aggiornamenti dell'interfaccia utente o l'elaborazione dell'input dell'utente, mentre il database completa l'operazione.
3. Applicazioni in tempo reale
Le applicazioni che richiedono polling frequente dei dati o aggiornamenti in tempo reale possono avviare query senza congelare il thread di esecuzione principale. Questo è particolarmente utile per strumenti di monitoraggio basati su CLI o endpoint web leggeri che devono rispondere rapidamente.
4. Elaborazione dati asincrona
Gli sviluppatori possono delegare attività di recupero dati pesanti al background mentre lo script principale elabora altri flussi di dati, migliorando il throughput complessivo nei workflow di elaborazione batch o ETL.
Vantaggi delle query non bloccanti di MySQLi
Le query non bloccanti di MySQLi offrono diversi vantaggi per gli sviluppatori PHP:
1. Prestazioni migliorate
Eseguendo le query in modo asincrono, l'esecuzione di altro codice non viene bloccata, con conseguente miglioramento delle prestazioni dell'applicazione. Questo è particolarmente vantaggioso per le applicazioni che aggregano dati da più sorgenti o gestiscono richieste ad alta concorrenza.
2. Migliore utilizzo delle risorse
L'esecuzione non bloccante consente al processo PHP di rimanere reattivo in attesa di operazioni sul database, riducendo i tempi di inattività e migliorando l'utilizzo delle risorse del server.
3. Gestione semplificata dei task in background
Gli sviluppatori possono concatenare più operazioni sul database senza annidare callback o macchine a stati complesse, rendendo il codice più facile da leggere e mantenere per gli script PHP procedurali standard.
Conclusione
mysqli_reap_async_query() è il passo finale del flusso di lavoro delle query asincrone di MySQLi: avvii una query con il flag MYSQLI_ASYNC, la attendi con mysqli_poll(), e poi ne raccogli il risultato. Usate insieme, queste funzioni permettono a uno script PHP di eseguire più query contro MySQL in parallelo e raccogliere i risultati man mano che arrivano, invece di aspettare ciascuna in sequenza. Il vantaggio maggiore si ha quando hai più query indipendenti — l'attesa totale scende approssimativamente alla query più lenta anziché alla somma di tutte. Ricorda le due regole fondamentali: una query asincrona per connessione, e non raccogliere mai il risultato prima che mysqli_poll() segnali che la connessione è pronta.
Argomenti correlati
- mysqli_poll — attende che una o più connessioni asincrone diventino pronte.
- mysqli_multi_query — esegue più istruzioni in una singola chiamata.
- mysqli_query — la funzione di query standard (sincrona).
- mysqli_connect — apre le connessioni su cui eseguire le query.
- PHP MySQLi — panoramica dell'estensione MySQLi.