これはのみ発生していることがわかります @status
の場合 NULL
です または文字列。
問題は2つあります:
-
ローカル変数 とは異なります 、MySQL ユーザー変数 非常に限られたデータ型のセットをサポートします:
ドキュメントには、実際のデータ型 については記載されていません。 使用されるのはそれぞれ
BIGINT
、DECIMAL(65,30)
、DOUBLE
、LONGBLOB
、LONGTEXT
およびLONGBLOB
。最後のものに関しては、マニュアルは少なくとも説明しています:ストレージ これらのデータ型の最初の3つ(つまり、整数、10進数、および浮動小数点値の場合)には、それぞれ8、30、および8バイトが必要です。その他のデータ型(つまり、文字列と
NULL
の場合 値)require(最大)4ギガバイト ストレージの。 -
v5.4.0より前のバージョンのPHPを使用しているため、デフォルトのMySQLドライバーは libmysql 、データバインディング時にサーバーから利用できるのは列タイプのメタデータのみです。したがって、MySQLiは、すべての可能な値を保持するのに十分なメモリを割り当てようとします(最終的にフルバッファが必要ない場合でも)。したがって、
NULL
-および文字列値のユーザー変数は、可能な最大サイズが4GiBであるため、PHPがデフォルトのメモリ制限(PHP v5.2.0以降は128MiB)を超えます。
オプションは次のとおりです。
-
テーブル定義の列データ型をオーバーライドする:
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');
-
ネイティブmysqlndドライバー を使用するように構成されたPHPの再コンパイル (v5.3.0以降はPHPに含まれていますが、PHP v5.4.0まではデフォルトとして構成されていません)libmysqlの代わりに:
./configure --with-mysqli=mysqlnd
-
mysqlndがデフォルトで使用されるようにPHPv5.4.0以降にアップグレードします。