reap_async_query
Apprenez comment mysqli_reap_async_query() récupère le résultat d'une requête MySQLi asynchrone en PHP, avec un exemple de requêtes parallèles via mysqli_poll.
Introduction
mysqli_reap_async_query() récupère le résultat d'une requête lancée de façon asynchrone avec l'extension MySQLi. Une requête asynchrone est une requête que vous déclenchez sans attendre que le serveur ait terminé — votre script PHP continue de s'exécuter, et vous collectez le résultat plus tard, une fois que le serveur signale qu'il est prêt.
C'est la pièce manquante du flux de travail asynchrone de MySQLi. Seule, mysqli_reap_async_query() ne sert à rien : elle n'a de sens qu'en tant que dernière étape d'un schéma en trois parties composé de mysqli_query(..., MYSQLI_ASYNC) (ou mysqli_send_query()), mysqli_poll(), et mysqli_reap_async_query(). Cette page explique comment ces éléments s'assemblent, présente un exemple complet exécutable et liste les pièges courants.
Prérequis : les requêtes asynchrones ne fonctionnent qu'avec le pilote mysqlnd (le pilote natif par défaut dans les versions modernes de PHP). Elles ne sont pas disponibles lorsque MySQLi est compilé avec l'ancien
libmysqlclient.
Le cycle de vie d'une requête asynchrone
Une requête asynchrone passe par trois étapes :
- Envoi — démarrez la requête avec le flag
MYSQLI_ASYNC.mysqli_query($conn, $sql, MYSQLI_RESULT, MYSQLI_ASYNC)(ou le raccourcimysqli_send_query()) retourne immédiatement sans attendre les résultats. - Sondage — appelez
mysqli_poll()pour attendre qu'une ou plusieurs connexions aient un résultat prêt. C'est ici que vous bloquez (avec un délai d'attente que vous contrôlez), au lieu de bloquer sur la requête elle-même. - Récupération — une fois que le sondage signale qu'une connexion est prête, appelez
mysqli_reap_async_query($conn)pour récupérer lemysqli_resultde cette connexion.
L'intérêt de cette approche réside dans l'étape de sondage. Vous pouvez placer plusieurs connexions dans un seul appel à mysqli_poll() et faire exécuter toutes leurs requêtes sur le serveur en même temps. Le temps d'attente total devient alors environ celui de la requête la plus lente, et non la somme de toutes.
mysqli_poll() : l'étape incontournable
Une erreur fréquente consiste à appeler mysqli_reap_async_query() directement après l'envoi d'une requête. Si le résultat n'est pas encore prêt, la récupération retourne false et génère une erreur — elle n'attend pas. C'est mysqli_poll() qui attend.
mysqli_poll() prend des tableaux de connexions passés par référence et un délai d'attente :
mysqli_poll($read, $error, $reject, $sec, $usec);$read— un tableau des connexions à surveiller. Après l'appel, il est réduit aux seules connexions ayant un résultat en attente.$error/$reject— reçoivent les connexions avec des erreurs de protocole ou des requêtes rejetées.$sec/$usec— durée d'attente, en secondes et microsecondes.
La fonction retourne le nombre de connexions prêtes (0 en cas de délai d'attente dépassé, false en cas d'échec).
Exemple complet : exécuter deux requêtes en parallèle
L'exemple ci-dessous ouvre deux connexions, lance une requête asynchrone sur chacune, sonde jusqu'à ce que les résultats arrivent, puis les récupère. Remplacez les identifiants et le SQL par les vôtres.
<?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--;
}
}
?>Chaque connexion ne peut exécuter qu'une seule requête asynchrone à la fois — c'est pourquoi l'exemple utilise une connexion séparée par requête. Réutilisez une connexion pour une nouvelle requête asynchrone seulement après avoir récupéré le résultat précédent.
Résumé étape par étape
- Ouvrez une connexion par requête à exécuter simultanément (
mysqli_connect()). - Démarrez chaque requête avec le flag
MYSQLI_ASYNCpour que l'appel retourne immédiatement. - Collectez les connexions dans un tableau et passez-le à
mysqli_poll()avec un délai d'attente. - Pour chaque connexion signalée comme prête par
mysqli_poll(), appelezmysqli_reap_async_query(). - Traitez le
mysqli_resultretourné, puis libérez-le avecmysqli_free_result().
Valeurs de retour et gestion des erreurs
mysqli_reap_async_query() retourne :
- Un objet
mysqli_resultpour les requêtes qui produisent un ensemble de résultats (ex.SELECT). truepour les requêtes qui ne retournent pas de lignes (INSERT,UPDATE,DELETE) lorsqu'elles réussissent.falseen cas d'échec, ou si elle est appelée avant que le résultat soit prêt — vérifiezmysqli_error()dans ce cas.
Conditionnez toujours la récupération derrière mysqli_poll(). Récupérer une connexion qui n'est pas prête est la source la plus fréquente de retours false inexpliqués.
Cas d'utilisation des requêtes non bloquantes MySQLi
Les requêtes non bloquantes MySQLi sont utiles pour les développeurs PHP qui doivent exécuter plusieurs requêtes en parallèle ou lancer des requêtes longues sans bloquer l'exécution du reste du code. Voici quelques cas d'utilisation pratiques :
1. Exécution parallèle de requêtes
Les développeurs peuvent utiliser les requêtes non bloquantes MySQLi pour exécuter plusieurs requêtes indépendantes en parallèle. En envoyant chaque requête avec mysqli_send_query() et en intercalant d'autre logique, les applications peuvent réduire les temps d'attente globaux lors de la récupération de données depuis plusieurs tables ou services.
2. Requêtes longues
Les requêtes longues peuvent être initiées de façon asynchrone pour que le script PHP puisse traiter d'autres tâches, comme la journalisation, les mises à jour d'interface ou le traitement des saisies utilisateur, pendant que la base de données finalise l'opération.
3. Applications en temps réel
Les applications nécessitant un sondage fréquent des données ou des mises à jour en temps réel peuvent initier des requêtes sans figer le fil d'exécution principal. Cela est particulièrement utile pour les outils de surveillance en ligne de commande ou les points d'accès web légers devant répondre rapidement.
4. Traitement de données asynchrone
Les développeurs peuvent décharger les tâches de récupération de données volumineuses pour qu'elles s'exécutent en arrière-plan pendant que le script principal traite d'autres flux de données, améliorant ainsi le débit global dans les workflows de traitement par lots ou ETL.
Avantages des requêtes non bloquantes MySQLi
Les requêtes non bloquantes MySQLi offrent plusieurs avantages aux développeurs PHP :
1. Performances améliorées
En exécutant les requêtes de façon asynchrone, l'exécution du reste du code n'est pas bloquée, ce qui se traduit par de meilleures performances applicatives. C'est particulièrement bénéfique pour les applications qui agrègent des données provenant de plusieurs sources ou gèrent des requêtes à haute concurrence.
2. Meilleure utilisation des ressources
L'exécution non bloquante permet au processus PHP de rester réactif en attendant les opérations de base de données, réduisant les temps d'inactivité et améliorant l'utilisation des ressources serveur.
3. Gestion simplifiée des tâches en arrière-plan
Les développeurs peuvent enchaîner plusieurs opérations de base de données sans imbriquer des callbacks ou des machines à états complexes, ce qui rend le code plus lisible et plus facile à maintenir pour les scripts PHP procéduraux standard.
Conclusion
mysqli_reap_async_query() est la dernière étape du flux de travail de requête asynchrone de MySQLi : vous démarrez une requête avec le flag MYSQLI_ASYNC, attendez avec mysqli_poll(), puis récupérez le résultat. Utilisées ensemble, ces fonctions permettent à un script PHP d'exécuter plusieurs requêtes contre MySQL en parallèle et de collecter les résultats au fur et à mesure qu'ils arrivent, au lieu d'attendre chacun à son tour. Le gain le plus important est obtenu lorsque vous avez plusieurs requêtes indépendantes — le temps d'attente total tombe à environ celui de la requête la plus lente plutôt que la somme de toutes. N'oubliez pas les deux règles qui garantissent la fiabilité : une seule requête asynchrone par connexion, et ne récupérez jamais avant que mysqli_poll() indique que la connexion est prête.
Sujets connexes
- mysqli_poll — attendre qu'une ou plusieurs connexions asynchrones soient prêtes.
- mysqli_multi_query — exécuter plusieurs instructions en un seul appel.
- mysqli_query — la fonction de requête standard (synchrone).
- mysqli_connect — ouvrir les connexions sur lesquelles vous exécutez des requêtes.
- PHP MySQLi — vue d'ensemble de l'extension MySQLi.