如何防止内存大小耗尽的致命错误

时间:2014-01-07 14:51:35

标签: php mysql memory-management

我正在使用datetime检索10K记录(包含10列,数据类型为textintvarcharmysql_fetch_object)并从中获取所有列每个在查询中加入表,这给了内存大小耗尽致命错误,但后来我修改了查询只得到一些消除错误的特定列,使我免于淹没在错误的湖中。

查询只是简单地连接3个表,A,B,C为SELECT * FROM A JOIN B ON ......JOIN C ON ...... WHERE.....

但是我仍然害怕如果没有。记录或否。列增加,然后错误将再次出现....那么这将是什么完整的解决方案?我在SO上阅读了其他帖子,发现应该使用mysql_unbuffered_query。但如果我使用mysql_fetch_object,是否没有解决方案?此外,无缓冲查询会花费更多时间,因为它一次返回一行吗?

1 个答案:

答案 0 :(得分:2)

MySQL不是这里耗尽的内存,它是你的PHP脚本,因此减少SELECT的大小只是部分解决方案。

我的猜测是你正在做的事情:

$collect = array();
while (has_records) {
    $collect[] = fetch_record;
}
foreach ($collect as $row) {
    handle_record($row);
}

当然$collect会变得非常大。看看你是否可以避免收集所有记录:读取记录,处理它,清理内存并进行下一次迭代。

while (has_records) {
    var $row = fetch_record();
    handle_record($row);
}

Iterator示例代码:

class DB {
    function get_iterator($query) {
        $query_result = do_query($query);
        return new Iterator($query_result);
    }
}

class MyIterator {
    public function __construct($mysql_result) {
        $this->res = $mysql_result;
    }
    public function hasMore() {
        // do some counting
    }
    public function fetch() {
        return mysql_fetch($this->res);
    }
}

echo '<table>';
$it = $db->get_iterator("SELECT * FROM `items`");
while($it->hasMore()) {
    echo '<tr>';
    $row = $it->fetch();
    foreach ($row as $cell) {
        echo '<td>' . $cell . '</td>';
    }
    echo '</tr>';
}
echo '</table>';

您甚至可以implements Iterator,因此您可以直接foreach超过$it,这很棒。