在优化我的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中的查询运行正常,返回的'note'大小不到千字节。
一个奇怪的事情是,它试图分配50331646的大小是十六进制的0x2FFFFFE,这是一个可疑的圆数。这几乎就像PHP试图分配一个足够大的缓冲区来保存最大的中间文本字段,而不是实际为所检索的数据分配内存。
任何人都知道解决方法 - 除了增加PHP中允许的最大内存?
btw其他人有同样的问题,但似乎不知道如何解决它。 Out of memory (allocated 50855936) (tried to allocate 50331646 bytes)
爆炸的确切线是:
$statement->bind_result(
$content_contentID,
$content_text,
$content_datestamp,
$note_noteID,
$note_contentID,
$note_text);
更改查询以选择“'测试字符串'作为注释”,而不是提取列不再显示大量内存使用情况。
btw我确信我不是想要检索大数据。这显示了注释表中的mediumtext字段的实际长度:
select length(text) from basereality.note;
+--------------+
| length(text) |
+--------------+
| 938 |
| 141 |
| 1116 |
| 431 |
| 334 |
+--------------+
答案 0 :(得分:4)
我找到了答案并在另一个问题中发表了评论:
Allowed memory size of 67108864 bytes exhausted
基本上,在旧的MySQL连接器库中,不是仅仅分配字段'text'的实际大小来存储结果,而是分配类型mediumtext的最大可能大小。
即。即使结果的字段仅为100千字节,也始终会分配16兆字节。
解决此问题的最简单且可能最好的方法是切换到使用不显示此行为的新MySQLND连接器。
答案 1 :(得分: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