Você descobrirá que isso está ocorrendo somente quando
@status
é NULL
ou uma corda. O problema é duplo:
-
Ao contrário das variáveis locais , MySQL variáveis de usuário suportam um conjunto muito limitado de tipos de dados:
A documentação não menciona que os tipos de dados reais usados são respectivamenteBIGINT
,DECIMAL(65,30)
,DOUBLE
,LONGBLOB
,LONGTEXT
eLONGBLOB
. Em relação ao último, o manual pelo menos explica:
Armazenamento dos três primeiros desses tipos de dados (ou seja, para valores inteiros, decimais e de ponto flutuante) requerem 8, 30 e 8 bytes, respectivamente. Os outros tipos de dados (ou seja, para string eNULL
valores) requerem (até) 4 gigabytes de armazenamento.
-
Como você está usando uma versão do PHP anterior à v5.4.0, o driver padrão do MySQL é libmysql , com o qual apenas metadados do tipo coluna estão disponíveis no servidor na vinculação de dados - então o MySQLi tenta alocar memória suficiente para armazenar todos os valores possíveis (mesmo que o buffer completo não seja necessário); assimNULL
- e variáveis de usuário com valor de string, que têm um tamanho máximo possível de 4GiB, fazem com que o PHP exceda seu limite de memória padrão (de 128MiB desde o PHP v5.2.0).
Suas opções incluem:
-
Substituindo o tipo de dados da coluna na definição da tabela:
DROP TEMPORARY TABLE IF EXISTS tmp_table; CREATE TEMPORARY TABLE tmp_table ( status VARCHAR(2) ) SELECT @status AS status;
-
Explicitamente transmissão a variável do usuário para um tipo de dados mais específico:
DROP TEMPORARY TABLE IF EXISTS tmp_table; CREATE TEMPORARY TABLE tmp_table SELECT CAST(@status AS CHAR(2)) AS status;
-
Usando variáveis locais, que são declaradas com um tipo de dados explícito:
DECLARE status VARCHAR(2) DEFAULT @status; DROP TEMPORARY TABLE IF EXISTS tmp_table; CREATE TEMPORARY TABLE tmp_table SELECT status;
-
Resolvendo o problema chamandomysqli_stmt::store_result()
antesmysqli_stmt::bind_result()
, que faz com que o conjunto de resultados seja armazenado em libmysql (fora dos limites de memória do PHP) e então o PHP alocará apenas a memória real necessária para manter o registro ao buscá-lo:
$stmt->execute(); $stmt->store_result(); $stmt->bind_result( $status ); $stmt->fetch();
-
Aumentando o limite de memória do PHP para que ele possa acomodar a alocação de buffers de 4GiB (embora se deva estar ciente das implicações nos recursos de hardware de fazê-lo) - por exemplo, para remover completamente as restrições de memória (embora esteja ciente dos possíveis efeitos colaterais negativos de fazer isso, por exemplo, de vazamentos de memória genuínos):
ini_set('memory_limit', '-1');
-
Recompilando o PHP, configurado para usar o driver mysqlnd nativo (incluído com PHP desde v5.3.0, mas não configurado como padrão até PHP v5.4.0) em vez de libmysql:
./configure --with-mysqli=mysqlnd
-
Atualizando para PHP v5.4.0 ou posterior para que o mysqlnd seja usado por padrão.