Mysql
 sql >> Baza danych >  >> RDS >> Mysql

Przyczyny błędu MySQL 2014 Nie można wykonać zapytań, gdy inne niebuforowane zapytania są aktywne

Protokół klienta MySQL nie pozwala na to, aby więcej niż jedno zapytanie było w toku. Oznacza to, że wykonałeś zapytanie i pobrałeś niektóre wyniki, ale nie wszystkie — następnie próbujesz wykonać drugie zapytanie. Jeśli pierwsze zapytanie nadal ma wiersze do zwrócenia, drugie zapytanie otrzymuje błąd.

Biblioteki klienckie omijają ten problem, pobierając wszystkie wiersze pierwszego zapytania niejawnie po pierwszym pobraniu, a kolejne pobranie po prostu iteruje po wewnętrznie buforowanych wynikach. Daje im to możliwość zamknięcia kursora (jeśli chodzi o serwer MySQL). To jest „zapytanie buforowane”. Działa to tak samo, jak przy użyciu fetchAll(), w tym przypadku oba przypadki muszą przydzielić wystarczającą ilość pamięci w kliencie PHP, aby pomieścić pełny zestaw wyników.

Różnica polega na tym, że buforowane zapytanie przechowuje wynik w bibliotece klienta MySQL, więc PHP nie może uzyskać dostępu do wierszy, dopóki nie pobierzesz każdego wiersza sekwencyjnie. Podczas gdy fetchAll() natychmiast wypełnia tablicę PHP dla wszystkich wyników, umożliwiając dostęp do dowolnego losowego wiersza.

Główny powód nie użycie fetchAll() oznacza, że ​​wynik może być zbyt duży, aby zmieścić się w twoim PHP memory_limit. Ale wygląda na to, że wyniki zapytania i tak mają tylko jeden wiersz, więc nie powinno to stanowić problemu.

Możesz zamknąć Cursor(), aby „porzucić” wynik przed pobraniem ostatniego wiersza. Serwer MySQL otrzymuje powiadomienie, że może odrzucić ten wynik po stronie serwera, a następnie możesz wykonać inne zapytanie. Nie powinieneś zamykać Cursor(), dopóki nie zakończysz pobierania danego zestawu wyników.

Ponadto:Zauważyłem, że ciągle wykonujesz $stmt2 wewnątrz pętli, ale za każdym razem zwróci ten sam wynik. Zgodnie z zasadą przenoszenia kodu niezmiennego pętli poza pętlę, powinieneś to zrobić raz przed rozpoczęciem pętli i zapisać wynik w zmiennej PHP. Więc niezależnie od używania zapytań buforowanych lub funkcji fetchAll(), nie ma potrzeby zagnieżdżania zapytań.

Zalecam więc pisanie kodu w ten sposób:

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

Uwaga:Użyłem również parametrów nazwanych zamiast parametrów pozycyjnych, co ułatwia przekazywanie $row jako tablicy wartości parametrów. Jeśli klucze tablicy pasują do nazw parametrów, możesz po prostu przekazać tablicę. W starszych wersjach PHP trzeba było dołączyć : prefiks w kluczach tablicy, ale już go nie potrzebujesz.

Mimo wszystko powinieneś używać mysqlnd. Ma więcej funkcji, jest bardziej wydajny pod względem pamięci, a jego licencja jest kompatybilna z PHP.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. aktualizowanie kolumn o numer kolejny mysql

  2. Zapowiedź ClusterControl 1.7.2:ulepszona kopia zapasowa PostgreSQL i wsparcie dla TimescaleDB i MySQL 8.0

  3. Jak działa funkcja INSTR() w MySQL

  4. Funkcja MySQL CRC32() – Przykłady

  5. SQL podziel wartości na wiele wierszy