W3docs

reap_async_query

Aprende cómo mysqli_reap_async_query() obtiene resultados de consultas asíncronas en PHP, con un ejemplo paralelo usando mysqli_poll.

Introducción

mysqli_reap_async_query() recupera el resultado de una consulta que se inició de forma asíncrona con la extensión MySQLi. Una consulta asíncrona es aquella que se lanza sin esperar a que el servidor termine: el script PHP sigue ejecutándose y recopila el resultado más tarde, una vez que el servidor indica que está listo.

Esta es la pieza que falta en el flujo de trabajo asíncrono de MySQLi. Por sí sola, mysqli_reap_async_query() no hace nada útil: solo tiene sentido como paso final de un patrón de tres partes formado por mysqli_query(..., MYSQLI_ASYNC) (o mysqli_send_query()), mysqli_poll() y mysqli_reap_async_query(). Esta página explica cómo encajan estas piezas, muestra un ejemplo completo y ejecutable, y enumera los errores más comunes.

Requisito: las consultas asíncronas solo funcionan con el controlador mysqlnd (el controlador nativo predeterminado en las versiones modernas de PHP). No están disponibles cuando MySQLi se compila contra el antiguo libmysqlclient.

El ciclo de vida de una consulta asíncrona

Una única consulta asíncrona pasa por tres etapas:

  1. Enviar — iniciar la consulta con el indicador MYSQLI_ASYNC. mysqli_query($conn, $sql, MYSQLI_RESULT, MYSQLI_ASYNC) (o la forma abreviada mysqli_send_query()) retorna inmediatamente sin esperar resultados.
  2. Sondear — llamar a mysqli_poll() para esperar hasta que una o más conexiones tengan un resultado listo. Aquí es donde se bloquea (con un tiempo de espera que tú controlas), en lugar de bloquearse en la consulta misma.
  3. Recoger — una vez que el sondeo informa que una conexión está lista, llamar a mysqli_reap_async_query($conn) para obtener el mysqli_result de esa conexión.

La razón por la que esto importa es el paso de sondeo. Puedes poner varias conexiones en una sola llamada a mysqli_poll() y hacer que todas sus consultas se ejecuten en el servidor al mismo tiempo. El tiempo de espera total es aproximadamente el de la consulta más lenta, no la suma de todas ellas.

mysqli_poll(): la parte que no puedes omitir

Un error común es llamar a mysqli_reap_async_query() directamente después de enviar una consulta. Si el resultado no está listo todavía, recoger devuelve false y establece un error — no espera. mysqli_poll() es la función que espera.

mysqli_poll() recibe arrays de conexiones pasados por referencia y un tiempo de espera:

mysqli_poll($read, $error, $reject, $sec, $usec);
  • $read — un array de las conexiones que deseas vigilar. Después de la llamada, se recorta solo a las conexiones que tienen un resultado esperando.
  • $error / $reject — reciben conexiones con errores de protocolo o solicitudes rechazadas.
  • $sec / $usec — cuánto tiempo esperar, en segundos y microsegundos.

Devuelve el número de conexiones listas (0 en tiempo de espera agotado, false en caso de fallo).

Ejemplo completo: ejecutar dos consultas en paralelo

El ejemplo siguiente abre dos conexiones, lanza una consulta asíncrona en cada una, sondea hasta que llegan los resultados y recoge cada uno. Sustituye las credenciales y el SQL por los tuyos.

<?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--;
    }
}
?>

Cada conexión solo puede ejecutar una consulta asíncrona a la vez — por eso el ejemplo usa una conexión separada por consulta. Reutiliza una conexión para una nueva consulta asíncrona solo después de haber recogido el resultado anterior.

Resumen paso a paso

  1. Abre una conexión por cada consulta que desees ejecutar de forma concurrente (mysqli_connect()).
  2. Inicia cada consulta con el indicador MYSQLI_ASYNC para que la llamada retorne inmediatamente.
  3. Reúne las conexiones en un array y pásalo a mysqli_poll() con un tiempo de espera.
  4. Para cada conexión que mysqli_poll() reporte como lista, llama a mysqli_reap_async_query().
  5. Procesa el mysqli_result devuelto y luego libéralo con mysqli_free_result().

Valores de retorno y manejo de errores

mysqli_reap_async_query() devuelve:

  • Un objeto mysqli_result para consultas que producen un conjunto de resultados (p. ej., SELECT).
  • true para consultas que no devuelven filas (INSERT, UPDATE, DELETE) cuando tienen éxito.
  • false en caso de fallo, o cuando se llama antes de que el resultado esté listo — en ese caso comprueba mysqli_error().

Siempre protege la recolección detrás de mysqli_poll(). Recoger una conexión que no está lista es la fuente más común de retornos false misteriosos.

Casos de uso para consultas no bloqueantes de MySQLi

Las consultas no bloqueantes de MySQLi son útiles para los desarrolladores PHP que necesitan realizar múltiples consultas en paralelo o ejecutar consultas de larga duración sin bloquear la ejecución de otro código. A continuación se presentan algunos casos de uso prácticos para este enfoque:

1. Ejecución de consultas en paralelo

Los desarrolladores pueden usar consultas no bloqueantes de MySQLi para ejecutar múltiples consultas independientes en paralelo. Al enviar cada consulta con mysqli_send_query() e intercalar otra lógica, las aplicaciones pueden reducir los tiempos de espera generales al obtener datos de múltiples tablas o servicios.

2. Consultas de larga duración

Las consultas de larga duración pueden iniciarse de forma asíncrona para que el script PHP pueda manejar otras tareas, como el registro, las actualizaciones de la interfaz de usuario o el procesamiento de la entrada del usuario, mientras la base de datos completa la operación.

3. Aplicaciones en tiempo real

Las aplicaciones que requieren sondeos frecuentes de datos o actualizaciones en tiempo real pueden iniciar consultas sin congelar el hilo de ejecución principal. Esto es especialmente útil para herramientas de monitorización basadas en CLI o endpoints web ligeros que necesitan responder rápidamente.

4. Procesamiento asíncrono de datos

Los desarrolladores pueden delegar tareas pesadas de recuperación de datos para que se ejecuten en segundo plano mientras el script principal procesa otros flujos de datos, mejorando el rendimiento general en flujos de trabajo de procesamiento por lotes o ETL.

Ventajas de las consultas no bloqueantes de MySQLi

Las consultas no bloqueantes de MySQLi ofrecen varias ventajas para los desarrolladores PHP:

1. Rendimiento mejorado

Al ejecutar consultas de forma asíncrona, la ejecución de otro código no se bloquea, lo que resulta en un rendimiento de la aplicación más rápido. Esto es especialmente beneficioso para aplicaciones que agregan datos de múltiples fuentes o manejan solicitudes de alta concurrencia.

2. Mejor utilización de recursos

La ejecución no bloqueante permite que el proceso PHP permanezca receptivo mientras espera operaciones de base de datos, reduciendo el tiempo de inactividad y mejorando la utilización de recursos del servidor.

3. Gestión simplificada de tareas en segundo plano

Los desarrolladores pueden encadenar múltiples operaciones de base de datos sin anidar callbacks ni máquinas de estado complejas, haciendo el código más fácil de leer y mantener para scripts PHP procedurales estándar.

Conclusión

mysqli_reap_async_query() es el paso final del flujo de trabajo de consultas asíncronas de MySQLi: inicias una consulta con el indicador MYSQLI_ASYNC, la esperas con mysqli_poll() y luego recoges el resultado. Usadas juntas, estas funciones permiten que un script PHP ejecute varias consultas contra MySQL en paralelo y recopile los resultados a medida que finalizan, en lugar de esperar por cada una a su vez. El mayor beneficio es cuando tienes múltiples consultas independientes: el tiempo de espera total cae a aproximadamente la consulta más lenta en lugar de la suma de todas ellas. Recuerda las dos reglas que mantienen esto fiable: una consulta asíncrona por conexión y nunca recoger antes de que mysqli_poll() indique que la conexión está lista.

Temas relacionados

  • mysqli_poll — esperar a que una o más conexiones asíncronas estén listas.
  • mysqli_multi_query — ejecutar varias sentencias en una sola llamada.
  • mysqli_query — la función de consulta estándar (síncrona).
  • mysqli_connect — abrir las conexiones sobre las que se ejecutan las consultas.
  • PHP MySQLi — descripción general de la extensión MySQLi.

Práctica

Práctica
¿Qué es correcto acerca de ejecutar una consulta MySQL en PHP usando el método reap async query?
¿Qué es correcto acerca de ejecutar una consulta MySQL en PHP usando el método reap async query?
Was this page helpful?