5

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 |
+--------------+
4

2 に答える 2

4

私は答えを見つけて、別の質問にコメントしました:

67108864 バイトの許容メモリ サイズを使い果たしました

基本的に、古い MySQL コネクタ ライブラリでは、フィールド 'text' の実際のサイズを単に割り当てて結果を格納するのではなく、タイプ mediumtext の可能な最大サイズが割り当てられます。

つまり、結果のフィールドが 100 キロバイトしかない場合でも、常に 16 メガバイトが割り当てられます。

これを修正する最も簡単でおそらく最善の方法は、この動作を示さない新しい MySQLND コネクタの使用に切り替えることです。

于 2012-11-21T00:21:15.733 に答える
0

mysqli_store_result を試しましたか? 以下の php.net リンクを見てください。より多くの人が同じ問題を抱えており、結果をバインドする前に store_result を呼び出すことで解決した人もいます。

http://php.net/manual/en/mysqli.store-result.php

http://dev.mysql.com/doc/refman/5.0/en/mysql-stmt-store-result.html

于 2012-08-13T21:16:48.060 に答える