Du kommer att upptäcka att detta endast sker när @status
är NULL
eller en sträng.
Problemet är dubbelt:
-
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
ochLONGBLOB
. 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. -
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öremysqli_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.