Dan*_*ack 5 php memory apache mysqli
在优化我的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;
Run Code Online (Sandbox Code Playgroud)
而爆炸的查询是:
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 ;
Run Code Online (Sandbox Code Playgroud)
在服务器上的MySQL中运行查询运行正常,返回的'note'大小不到千字节.
一个奇怪的是它试图分配50331646的大小是十六进制的0x2FFFFFE,这是一个可疑的圆数.这几乎就像PHP试图分配一个足够大的缓冲区来保存最大的中间文本字段,而不是实际为所检索的数据分配内存.
任何人都知道一个解决方法 - 除了增加PHP允许的最大内存?
顺便说一句其他人有同样的问题,但似乎不知道如何解决它. 内存不足(分配50855936)(试图分配50331646字节)
爆炸的确切线是:
$statement->bind_result(
$content_contentID,
$content_text,
$content_datestamp,
$note_noteID,
$note_contentID,
$note_text);
Run Code Online (Sandbox Code Playgroud)
更改查询以选择"'测试字符串'作为注释",而不是获取列不再显示大量内存使用情况.
顺便说一下,我确信我不会尝试检索大数据.这显示了注释表中的mediumtext字段的实际长度:
select length(text) from basereality.note;
+--------------+
| length(text) |
+--------------+
| 938 |
| 141 |
| 1116 |
| 431 |
| 334 |
+--------------+
Run Code Online (Sandbox Code Playgroud)
我找到了答案并在另一个问题中评论:
基本上,在旧的MySQL连接器库中,不只是分配“text”字段的实际大小来存储结果,而是分配mediumtext类型的最大可能大小。
即,即使结果字段只有 100 KB,也始终分配 16 MB。
解决此问题最简单也可能是最好的方法是改用新的 MySQLND 连接器,该连接器不会显示此行为。