sql >> Databasteknik >  >> RDS >> Mysql

PHP mysql_stmt::fetch() ger PHP Fatal-felminne uttömt

Du kommer att upptäcka att detta endast sker när @status är NULL eller en sträng.

Problemet är dubbelt:

  1. Till skillnad från lokala variabler , MySQL användarvariabler stöder en mycket begränsad uppsättning datatyper:

    Dokumentationen nämner inte att de faktiska datatyperna som används är respektive BIGINT , DECIMAL(65,30) , DOUBLE , LONGBLOB , LONGTEXT och LONGBLOB . När det gäller den sista förklarar manualen åtminstone:

    Lagring av de tre första av dessa datatyper (d.v.s. för heltals-, decimal- och flyttalsvärden) kräver 8, 30 respektive 8 byte. De andra datatyperna (dvs för sträng och NULL värden) kräver (upp till) 4 gigabyte lagring.

  2. Eftersom du använder en version av PHP före v5.4.0 är standarddrivrutinen för MySQL libmysql , med vilken endast kolumntypsmetadata är tillgänglig från servern vid databindning—så MySQLi försöker allokera tillräckligt med minne för att hålla alla möjliga värden (även om den fulla bufferten inte krävs i slutändan); alltså NULL - och strängvärdade användarvariabler, som har en maximal möjlig storlek på 4GiB, gör att PHP överskrider standardminnesgränsen (på 128MiB sedan PHP v5.2.0).

Dina alternativ inkluderar:

  • Åsidosätt kolumndatatypen i tabelldefinitionen:

    DROP TEMPORARY TABLE IF EXISTS tmp_table;
    CREATE TEMPORARY TABLE tmp_table (
      status VARCHAR(2)
    ) SELECT @status AS status;
    
  • Explicit casting användarvariabeln till en mer specifik datatyp:

    DROP TEMPORARY TABLE IF EXISTS tmp_table;
    CREATE TEMPORARY TABLE tmp_table
      SELECT CAST(@status AS CHAR(2)) AS status;
    
  • Använda lokala variabler, som deklareras med en explicit datatyp:

    DECLARE status VARCHAR(2) DEFAULT @status;
    DROP TEMPORARY TABLE IF EXISTS tmp_table;
    CREATE TEMPORARY TABLE tmp_table
      SELECT status;
    
  • Lös problemet genom att anropa mysqli_stmt::store_result() före mysqli_stmt::bind_result() , vilket gör att resultatuppsättningen lagras i libmysql (utanför PHPs minnesgränser) och då kommer PHP bara att allokera det faktiska minnet som krävs för att hålla posten när den hämtas:

    $stmt->execute();
    $stmt->store_result();
    $stmt->bind_result( $status );
    $stmt->fetch();
    
  • Höjer PHPs minnesgräns så att den kan ta emot allokeringen av 4GiB-buffertar (även om man bör vara medveten om konsekvenserna för hårdvaruresurser av att göra det) - till exempel för att ta bort minnesbegränsningarna helt (även om man är medveten om potentiella negativa bieffekter av att göra detta, t.ex. från äkta minnesläckor):

    ini_set('memory_limit', '-1');
    
  • Återkompilera PHP, konfigurerad för att använda den inbyggda mysqlnd-drivrutinen (ingår med PHP sedan v5.3.0, men inte konfigurerat som standard förrän PHP v5.4.0) istället för libmysql:

    ./configure --with-mysqli=mysqlnd
    
  • Uppgraderar till PHP v5.4.0 eller senare så att mysqlnd används som standard.




  1. Ta reda på var din PHP-kod saktar ner (prestandaproblem)

  2. MySQL JOIN med IF-villkor

  3. Använda markörer för personsökning i PostgreSQL

  4. MAX() Funktion i PostgreSQL