Ще откриете, че това се случва само когато @status
е NULL
или низ.
Проблемът е двоен:
-
За разлика от локалните променливи , MySQL потребителски променливи поддържат много ограничен набор от типове данни:
В документацията не се споменава, че действителните типове данни използвани са съответно
BIGINT
,DECIMAL(65,30)
,DOUBLE
,LONGBLOB
,LONGTEXT
иLONGBLOB
. По отношение на последното ръководството поне обяснява:Съхранение от първите три от тези типове данни (т.е. за цели числа, десетични стойности и стойности с плаваща запетая) изискват съответно 8, 30 и 8 байта. Другите типове данни (т.е. за низ и
NULL
стойности) изискват (до) 4 гигабайта на съхранение. -
Тъй като използвате версия на PHP преди v5.4.0, драйверът за MySQL по подразбиране е libmysql , с който само метаданни от тип колона са достъпни от сървъра при обвързване на данни – така че MySQLi се опитва да разпредели достатъчно памет, за да задържи всяка възможна стойност (дори ако пълният буфер в крайна сметка не е необходим); така
NULL
- и потребителски променливи с низови стойности, които имат максимален възможен размер от 4GiB, карат PHP да надвиши лимита си за памет по подразбиране (от 128MiB от PHP v5.2.0).
Вашите опции включват:
-
Отмяна на типа данни на колоната в дефиницията на таблицата:
DROP TEMPORARY TABLE IF EXISTS tmp_table; CREATE TEMPORARY TABLE tmp_table ( status VARCHAR(2) ) SELECT @status AS status;
-
Изрично прехвърляне потребителската променлива към по-специфичен тип данни:
DROP TEMPORARY TABLE IF EXISTS tmp_table; CREATE TEMPORARY TABLE tmp_table SELECT CAST(@status AS CHAR(2)) AS status;
-
Използване на локални променливи, които са декларирани с изричен тип данни:
DECLARE status VARCHAR(2) DEFAULT @status; DROP TEMPORARY TABLE IF EXISTS tmp_table; CREATE TEMPORARY TABLE tmp_table SELECT status;
-
Заобикаляне на проблема чрез извикване на
mysqli_stmt::store_result()
предиmysqli_stmt::bind_result()
, което кара набора от резултати да се съхранява в libmysql (извън ограниченията на паметта на PHP) и след това PHP ще разпредели само действителната памет, необходима за съхраняване на записа при изтеглянето му:$stmt->execute(); $stmt->store_result(); $stmt->bind_result( $status ); $stmt->fetch();
-
Повишаване на лимит на паметта на PHP така че да може да побере разпределението на 4GiB буфери (въпреки че човек трябва да е наясно с последиците за хардуерните ресурси от това) - например, за да премахне изцяло ограниченията на паметта (въпреки че е наясно с потенциалните отрицателни странични ефекти от това, например от изтичане на истинска памет):
ini_set('memory_limit', '-1');
-
Прекомпилиране на PHP, конфигуриран да използва родния драйвер за mysqlnd (включен с PHP от v5.3.0, но не е конфигуриран по подразбиране до PHP v5.4.0) вместо libmysql:
./configure --with-mysqli=mysqlnd
-
Надстройка до PHP v5.4.0 или по-нова версия, така че mysqlnd да се използва по подразбиране.