sql >> Databasteknik >  >> RDS >> Mysql

Orsaker till MySQL-fel 2014 Kan inte köra frågor medan andra obuffrade frågor är aktiva

MySQL-klientprotokollet tillåter inte att mer än en fråga "pågår". Det vill säga, du har kört en fråga och du har hämtat några av resultaten, men inte alla -- sedan försöker du köra en andra fråga. Om den första frågan fortfarande har rader att returnera, får den andra frågan ett fel.

Klientbibliotek kommer runt detta genom att hämta alla raderna i den första frågan implicit vid första hämtning, och sedan efterföljande hämtningar, itererar helt enkelt över de internt cachade resultaten. Detta ger dem möjlighet att stänga markören (när det gäller MySQL-servern). Detta är den "buffrade frågan". Detta fungerar på samma sätt som att använda fetchAll(), eftersom båda fallen måste allokera tillräckligt med minne i PHP-klienten för att hålla hela resultatuppsättningen.

Skillnaden är att en buffrad fråga håller resultatet i MySQL-klientbiblioteket, så PHP kan inte komma åt raderna förrän du hämtar() varje rad i följd. Medan fetchAll() omedelbart fyller i en PHP-array för alla resultat, vilket ger dig tillgång till valfri slumpmässig rad.

Den främsta orsaken till inte att använda fetchAll() är att ett resultat kan vara för stort för att passa i din PHP memory_limit. Men det verkar som om dina sökresultat bara har en rad ändå, så det borde inte vara något problem.

Du kan stänga Cursor() för att "överge" ett resultat innan du har hämtat den sista raden. MySQL-servern får ett meddelande om att den kan kassera det resultatet på serversidan, och sedan kan du köra en annan fråga. Du bör inte stänga Cursor() förrän du är klar med att hämta en given resultatuppsättning.

Dessutom:Jag märker att du kör din $stmt2 om och om igen i loopen, men den kommer att returnera samma resultat varje gång. Enligt principen att flytta loop-invariant kod ut ur loopen, bör du ha exekverat detta en gång innan du startar loopen, och sparat resultatet i en PHP-variabel. Så oavsett om du använder buffrade frågor eller fetchAll(), så behöver du inte kapsla dina frågor.

Så jag skulle rekommendera att du skriver din kod så här:

$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));}            
}

Notera att jag också använde namngivna parametrar istället för positionsparametrar, vilket gör det enklare att skicka $row som array av parametervärden. Om arrayens nycklar matchar parameternamnen kan du bara skicka arrayen. I äldre versioner av PHP var du tvungen att inkludera : prefix i array-nycklarna, men det behöver du inte längre.

Du bör använda mysqlnd ändå. Den har fler funktioner, den är mer minneseffektiv och dess licens är kompatibel med PHP.



  1. Introduktion till SQL Joins

  2. Exportera SQLite-frågeresultat till en CSV-fil

  3. Räkna ackumulerad summa i Postgresql

  4. Hur kan jag exportera innehållet i en orakeltabell till en fil?