Mysql
 sql >> Base de Dados >  >> RDS >> Mysql

Causas do erro MySQL 2014 Não é possível executar consultas enquanto outras consultas sem buffer estão ativas


O protocolo do cliente MySQL não permite que mais de uma consulta esteja "em andamento". Ou seja, você executou uma consulta e obteve alguns dos resultados, mas não todos -- então você tenta executar uma segunda consulta. Se a primeira consulta ainda tiver linhas para retornar, a segunda consulta receberá um erro.

As bibliotecas de cliente contornam isso buscando todos as linhas da primeira consulta implicitamente na primeira busca e, em seguida, as buscas subsequentes simplesmente iteram sobre os resultados armazenados em cache internamente. Isso lhes dá a oportunidade de fechar o cursor (no que diz respeito ao servidor MySQL). Esta é a "consulta em buffer". Isso funciona da mesma forma que usar fetchAll(), em que ambos os casos devem alocar memória suficiente no cliente PHP para manter o conjunto de resultados completo.

A diferença é que uma consulta em buffer mantém o resultado na biblioteca cliente MySQL, então o PHP não pode acessar as linhas até que você busque() cada linha sequencialmente. Enquanto fetchAll() preenche imediatamente um array PHP para todos os resultados, permitindo que você acesse qualquer linha aleatória.

A principal razão não usar fetchAll() é que um resultado pode ser muito grande para caber no seu PHP memory_limit. Mas parece que os resultados da sua consulta têm apenas uma linha, então isso não deve ser um problema.

Você pode fecharCursor() para "abandonar" um resultado antes de buscar a última linha. O servidor MySQL é notificado de que pode descartar esse resultado no lado do servidor e, em seguida, você pode executar outra consulta. Você não deve fecharCursor() até terminar de buscar um determinado conjunto de resultados.

Além disso:notei que você está executando seu $stmt2 repetidamente dentro do loop, mas ele retornará o mesmo resultado todas as vezes. No princípio de mover o código invariável de loop para fora do loop, você deve ter executado isso uma vez antes de iniciar o loop e salvo o resultado em uma variável PHP. Portanto, independentemente de usar consultas em buffer ou fetchAll(), não há necessidade de aninhar suas consultas.

Então, eu recomendaria escrever seu código desta maneira:
$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));}            
}

Observe que também usei parâmetros nomeados em vez de parâmetros posicionais, o que torna mais simples passar $row como a matriz de valores de parâmetro. Se as chaves do array corresponderem aos nomes dos parâmetros, você pode simplesmente passar o array. Em versões mais antigas do PHP você tinha que incluir o : prefix nas chaves do array, mas você não precisa mais disso.

Você deve usar o mysqlnd de qualquer maneira. Tem mais recursos, é mais eficiente em termos de memória e sua licença é compatível com PHP.