sql >> Database >  >> RDS >> Mysql

Oorzaken van MySQL-fout 2014 Kan geen query's uitvoeren terwijl andere niet-gebufferde query's actief zijn

Het MySQL-clientprotocol staat niet toe dat meer dan één query 'in uitvoering' is. Dat wil zeggen, je hebt een query uitgevoerd en je hebt een aantal van de resultaten opgehaald, maar niet alle -- dan probeer je een tweede query uit te voeren. Als de eerste query nog steeds rijen heeft om te retourneren, krijgt de tweede query een foutmelding.

Clientbibliotheken omzeilen dit door alles . op te halen de rijen van de eerste query impliciet bij de eerste keer ophalen, en de daaropvolgende ophaalacties herhalen eenvoudig de intern in de cache opgeslagen resultaten. Dit geeft hen de mogelijkheid om de cursor te sluiten (voor zover het de MySQL-server betreft). Dit is de 'gebufferde query'. Dit werkt hetzelfde als het gebruik van fetchAll(), in die zin dat in beide gevallen voldoende geheugen in de PHP-client moet worden toegewezen om de volledige resultatenset te bevatten.

Het verschil is dat een gebufferde query het resultaat vasthoudt in de MySQL-clientbibliotheek, zodat PHP geen toegang heeft tot de rijen totdat u elke rij opeenvolgend ophaalt(). Terwijl fetchAll() onmiddellijk een PHP-array vult voor alle resultaten, zodat je toegang hebt tot elke willekeurige rij.

De belangrijkste reden niet om fetchAll() te gebruiken, is dat een resultaat mogelijk te groot is om in uw PHP-geheugenlimiet te passen. Maar het lijkt erop dat uw zoekopdrachtresultaten toch maar één rij hebben, dus dat zou geen probleem moeten zijn.

U kunt Cursor() sluiten om een ​​resultaat te "verlaten" voordat u de laatste rij hebt opgehaald. De MySQL-server krijgt een melding dat het resultaat aan de serverzijde kan worden weggegooid, waarna u een nieuwe query kunt uitvoeren. Je moet Cursor() pas sluiten als je klaar bent met het ophalen van een bepaalde resultatenset.

Ook:ik merk dat je je $stmt2 keer op keer binnen de lus uitvoert, maar het zal elke keer hetzelfde resultaat opleveren. Volgens het principe van het verplaatsen van lus-invariante code uit de lus, zou u dit één keer moeten hebben uitgevoerd voordat u de lus start, en het resultaat in een PHP-variabele moeten opslaan. Dus ongeacht het gebruik van gebufferde zoekopdrachten of fetchAll(), u hoeft uw zoekopdrachten niet te nesten.

Dus ik zou aanraden om je code op deze manier te schrijven:

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

Opmerking Ik heb ook benoemde parameters gebruikt in plaats van positionele parameters, wat het eenvoudiger maakt om $row door te geven als de reeks parameterwaarden. Als de sleutels van de array overeenkomen met de parameternamen, kun je de array gewoon doorgeven. In oudere versies van PHP moest je de : prefix in de array-sleutels, maar dat heb je niet meer nodig.

Je zou toch mysqlnd moeten gebruiken. Het heeft meer functies, is geheugenefficiënter en de licentie is compatibel met PHP.



  1. SQL:verwijder alle gegevens uit alle beschikbare tabellen

  2. Geparametriseerde query in Oracle-problemen

  3. Sum, Avg en Count gebruiken in Select Statement - SQL Server / TSQL Tutorial Part 128

  4. Wat is het verschil tussen een tijdelijke tabel en een tabelvariabele in SQL Server?