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

PHP mysql_stmt::fetch() powoduje wyczerpanie pamięci błędów krytycznych PHP

Przekonasz się, że dzieje się tak tylko kiedy @status jest NULL lub ciąg.

Problem jest dwojaki:

  1. W przeciwieństwie do zmiennych lokalnych , MySQL zmienne użytkownika obsługuje bardzo ograniczony zestaw typów danych:

    Dokumentacja nie wspomina, że ​​rzeczywiste typy danych używane są odpowiednio BIGINT , DECIMAL(65,30) , DOUBLE , LONGBLOB , LONGTEXT i LONGBLOB . Jeśli chodzi o ostatnią, instrukcja przynajmniej wyjaśnia:

    Przechowywanie pierwszych trzech z tych typów danych (tj. dla wartości całkowitych, dziesiętnych i zmiennoprzecinkowych) wymaga odpowiednio 8, 30 i 8 bajtów. Inne typy danych (np. dla string i NULL wartości) wymagają (maksymalnie) 4 gigabajty pamięci.

  2. Ponieważ używasz wersji PHP przed 5.4.0, domyślnym sterownikiem MySQL jest libmysql , z którym tylko metadane typu kolumny są dostępne z serwera po powiązaniu danych — więc MySQLi próbuje przydzielić wystarczającą ilość pamięci do przechowywania każdej możliwej wartości (nawet jeśli pełny bufor nie jest ostatecznie wymagany); stąd NULL - a zmienne użytkownika o wartościach łańcuchowych, które mają maksymalny możliwy rozmiar 4GiB, powodują przekroczenie domyślnego limitu pamięci PHP (wynoszącego 128 MB od wersji 5.2.0 PHP).

Twoje opcje obejmują:

  • Zastępowanie typu danych kolumny w definicji tabeli:

    DROP TEMPORARY TABLE IF EXISTS tmp_table;
    CREATE TEMPORARY TABLE tmp_table (
      status VARCHAR(2)
    ) SELECT @status AS status;
    
  • Jawnie przesyłanie zmienną użytkownika do bardziej konkretnego typu danych:

    DROP TEMPORARY TABLE IF EXISTS tmp_table;
    CREATE TEMPORARY TABLE tmp_table
      SELECT CAST(@status AS CHAR(2)) AS status;
    
  • Używając zmiennych lokalnych, które są zadeklarowane z określonym typem danych:

    DECLARE status VARCHAR(2) DEFAULT @status;
    DROP TEMPORARY TABLE IF EXISTS tmp_table;
    CREATE TEMPORARY TABLE tmp_table
      SELECT status;
    
  • Obejście problemu przez wywołanie mysqli_stmt::store_result() przed mysqli_stmt::bind_result() , co powoduje, że zestaw wyników jest przechowywany w libmysql (poza limitami pamięci PHP), a następnie PHP przydzieli tylko rzeczywistą pamięć wymaganą do przechowywania rekordu po jego pobraniu:

    $stmt->execute();
    $stmt->store_result();
    $stmt->bind_result( $status );
    $stmt->fetch();
    
  • Zwiększenie limitu pamięci PHP tak, aby mógł pomieścić alokację buforów 4GiB (chociaż należy być świadomym konsekwencji dla zasobów sprzętowych z tego powodu) — na przykład, aby całkowicie usunąć ograniczenia pamięci (chociaż należy być świadomym potencjalnych negatywnych skutków ubocznych takiego postępowania, np. z prawdziwych wycieków pamięci):

    ini_set('memory_limit', '-1');
    
  • Ponowna kompilacja PHP, skonfigurowana do korzystania z natywnego sterownika mysqlnd (dołączony do PHP od v5.3.0, ale nie skonfigurowany jako domyślny do PHP v5.4.0) zamiast libmysql:

    ./configure --with-mysqli=mysqlnd
    
  • Aktualizacja do PHP w wersji 5.4.0 lub nowszej, tak aby mysqlnd był używany domyślnie.




  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. MySQL — Entity :wartość kolumny „IsPrimaryKey” w tabeli „TableDetails” to DBNull

  2. jak automatycznie wstawiać odniesienia do kluczy obcych w tabelach w mysql lub JDBC?

  3. Jak dodać domyślne ograniczenie w MySQL?

  4. Wymagania dotyczące obiektów blob i pamięci masowej

  5. Zapytanie o zamówienie według ostatnich trzech znaków w kolumnie