sql >> Databáze >  >> RDS >> Mysql

Příčiny chyby MySQL 2014 Nelze provádět dotazy, když jsou aktivní jiné dotazy bez vyrovnávací paměti

Klientský protokol MySQL neumožňuje, aby byl „probíhá“ více než jeden dotaz. To znamená, že jste provedli dotaz a získali jste některé výsledky, ale ne všechny - pak se pokusíte provést druhý dotaz. Pokud má první dotaz stále řádky k vrácení, druhý dotaz dostane chybu.

Klientské knihovny to obejdou načtením všech řádky prvního dotazu implicitně při prvním načtení a poté následná načtení jednoduše opakují výsledky interně uložené v mezipaměti. To jim dává možnost zavřít kurzor (pokud jde o server MySQL). Toto je „vyrovnávací dotaz“. Funguje to stejně jako použití fetchAll(), v tom případě musí oba případy alokovat dostatek paměti v klientovi PHP, aby podržel celou sadu výsledků.

Rozdíl je v tom, že dotaz ve vyrovnávací paměti uchovává výsledek v klientské knihovně MySQL, takže PHP nemůže přistupovat k řádkům, dokud nenačtete () každý řádek postupně. Zatímco fetchAll() okamžitě vyplní pole PHP pro všechny výsledky, což vám umožní přístup k libovolnému náhodnému řádku.

Hlavní důvod ne použití fetchAll() znamená, že výsledek může být příliš velký, aby se vešel do vašeho limitu paměti PHP. Zdá se však, že výsledky vašeho dotazu mají stejně jen jeden řádek, takže by to neměl být problém.

Můžete zavřít Cursor() a "opustit" výsledek předtím, než načtete poslední řádek. Server MySQL dostane upozornění, že může tento výsledek na straně serveru zahodit, a pak můžete provést další dotaz. Dokud nedokončíte načítání dané sady výsledků, neměli byste zavírat Cursor().

Také:Všiml jsem si, že provádíte $stmt2 znovu a znovu uvnitř smyčky, ale pokaždé vrátí stejný výsledek. Na principu přesouvání kódu neměnného smyčky ze smyčky byste to měli provést jednou před spuštěním smyčky a uložit výsledek do proměnné PHP. Takže bez ohledu na použití dotazů s vyrovnávací pamětí nebo fetchAll(), nemusíte své dotazy vnořovat.

Takže bych doporučil napsat váš kód takto:

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

Poznámka:Také jsem použil pojmenované parametry místo pozičních parametrů, což usnadňuje předávání $row jako pole hodnot parametrů. Pokud se klíče pole shodují s názvy parametrů, můžete pole jednoduše předat. Ve starších verzích PHP jste museli zahrnout : prefix v klíčích pole, ale už to nepotřebujete.

Stejně byste měli používat mysqlnd. Má více funkcí, je paměťově efektivnější a jeho licence je kompatibilní s PHP.



  1. 2 způsoby, jak získat krátký název měsíce z data v MariaDB

  2. Tipy pro ladění výkonu PostgreSQL

  3. Operátoři T-SQL SET Část 2:INTERSECT a EXCEPT

  4. PostgreSQL DESCRIBE TABLE Ekvivalent