Apache + PHP のメモリ使用量を最適化しているときに、奇妙な問題に遭遇しました。基本的に、MySQLi クエリの結果をバインドしようとすると、「致命的なエラー: 16777216 バイトの許容メモリ サイズが使い果たされました (50331646 バイトを割り当てようとしました)」というエラー メッセージが表示されてコードが爆発します。
関連するテーブルは次のとおりです。
CREATE TABLE `note` (
`noteID` int(11) NOT NULL AUTO_INCREMENT,
`contentID` int(11) NOT NULL,
`text` mediumtext NOT NULL,
PRIMARY KEY (`noteID`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE `content` (
`contentID` int(11) NOT NULL AUTO_INCREMENT,
`text` varchar(2048) NOT NULL,
`datestamp` datetime NOT NULL,
PRIMARY KEY (`contentID`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
爆発するクエリは次のとおりです。
select content.contentID,
content.text,
content.datestamp,
note.noteID,
note.contentID, note.text
from basereality.content as content
inner join basereality.note as note
on content.contentID = note.contentID
where content.contentID = 1028 ;
サーバー上の MySQL でクエリを実行すると問題なく実行され、返される「メモ」のサイズは 1 キロバイト未満です。
奇妙なことの 1 つは、50331646 を割り当てようとしているサイズが 16 進数で 0x2FFFFFE であることです。これは疑わしいラウンド数です。PHP は、取得したデータに実際にメモリを割り当てるのではなく、可能な限り最大の mediumtext フィールドを保持するのに十分な大きさのバッファを割り当てようとしているようです。
PHPで許可されている最大メモリを増やす以外に、これに対する回避策を知っている人はいますか?
ところで、他の人も同じ問題を抱えていましたが、解決方法を知らなかったようです。 メモリ不足 (割り当てられた 50855936) (50331646 バイトを割り当てようとしました)
爆発する正確な行は次のとおりです。
$statement->bind_result(
$content_contentID,
$content_text,
$content_datestamp,
$note_noteID,
$note_contentID,
$note_text);
クエリを変更して、列をフェッチするのではなく、「'A test string' as note」を選択すると、大量のメモリ使用量が表示されなくなりました。
ところで、私は大きなデータを取得しようとしていないと確信しています。これは、note テーブルの mediumtext フィールドの実際の長さを示しています。
select length(text) from basereality.note;
+--------------+
| length(text) |
+--------------+
| 938 |
| 141 |
| 1116 |
| 431 |
| 334 |
+--------------+