sql >> Base de Datos >  >> RDS >> Mysql

Causas del error de MySQL 2014 No se pueden ejecutar consultas mientras otras consultas sin búfer están activas

El protocolo de cliente MySQL no permite que haya más de una consulta "en curso". Es decir, ha ejecutado una consulta y ha obtenido algunos de los resultados, pero no todos; luego intenta ejecutar una segunda consulta. Si la primera consulta todavía tiene filas para devolver, la segunda consulta obtiene un error.

Las bibliotecas cliente solucionan esto recuperando todos las filas de la primera consulta implícitamente en la primera búsqueda, y luego las búsquedas subsiguientes simplemente iteran sobre los resultados almacenados en caché internamente. Esto les da la oportunidad de cerrar el cursor (en lo que respecta al servidor MySQL). Esta es la "consulta almacenada". Esto funciona igual que usar fetchAll(), en el sentido de que ambos casos deben asignar suficiente memoria en el cliente PHP para contener el conjunto de resultados completo.

La diferencia es que una consulta almacenada en búfer mantiene el resultado en la biblioteca del cliente MySQL, por lo que PHP no puede acceder a las filas hasta que busque () cada fila secuencialmente. Mientras que fetchAll() llena inmediatamente una matriz de PHP para todos los resultados, permitiéndole acceder a cualquier fila aleatoria.

La razón principal no usar fetchAll() es que un resultado podría ser demasiado grande para caber en su límite de memoria de PHP. Pero parece que los resultados de su consulta tienen solo una fila de todos modos, por lo que no debería ser un problema.

Puede closeCursor() para "abandonar" un resultado antes de obtener la última fila. El servidor MySQL recibe una notificación de que puede descartar ese resultado en el lado del servidor y luego puede ejecutar otra consulta. No debe cerrar Cursor() hasta que haya terminado de obtener un conjunto de resultados determinado.

Además:me doy cuenta de que está ejecutando su $stmt2 una y otra vez dentro del ciclo, pero devolverá el mismo resultado cada vez. Según el principio de sacar el código invariable del bucle fuera del bucle, debería haberlo ejecutado una vez antes de iniciar el bucle y guardado el resultado en una variable de PHP. Entonces, independientemente de usar consultas almacenadas en búfer o fetchAll(), no es necesario que anide sus consultas.

Entonces recomendaría escribir su código de esta manera:

$sql ='SELECT temp_id FROM temp1';
$stmt2 = db::db()->prepare($sql);
$stmt2->execute();
$rs2 = $stmt2->fetchAll(PDO::FETCH_ASSOC);
$stmt2->closeCursor();

$sql='SELECT COUNT(*) AS valid FROM cities_has_zipcodes 
      WHERE cities_id=:cities_id AND zipcodes_id=:zipcodes_id';
$stmt1 = db::db()->prepare($sql);

foreach($data AS $row)
{
    try
    {
        $stmt1->execute($row);
        $rs1 = $stmt1->fetchAll(PDO::FETCH_ASSOC);
        $stmt1->closeCursor();
        syslog(LOG_INFO,'$rs1: '.print_r($rs1[0],1).' '.rand());
        syslog(LOG_INFO,'$rs2: '.print_r($rs2[0],1).' '.rand());
    }
    catch(PDOException $e){echo(sql_error($e));}            
}

Tenga en cuenta que también usé parámetros con nombre en lugar de parámetros posicionales, lo que hace que sea más sencillo pasar $fila como la matriz de valores de parámetros. Si las claves de la matriz coinciden con los nombres de los parámetros, simplemente puede pasar la matriz. En versiones anteriores de PHP, tenía que incluir el : prefijo en las claves de matriz, pero ya no lo necesita.

Deberías usar mysqlnd de todos modos. Tiene más funciones, es más eficiente en memoria y su licencia es compatible con PHP.