运行我的一个脚本时,我一直收到此错误;
PHP致命错误:允许的内存大小 1073741824字节耗尽(尝试过 分配71个字节)... LIB / symfony的-1.4.11 / LIB /插件/ sfDoctrinePlugin / LIB /供应商/教义/学说/连接/ Statement.php 在第246行,......
以下是脚本的精简版本 触发错误;
public function executeImportFile(sfWebRequest $request)
{
ini_set('memory_limit', '1024M');
set_time_limit ( 0 );
//more codes here...
$files = scandir($workspace.'/'.$directory);
foreach ($files as $file) {
$path = $workspace.'/'.$directory.'/'.$file;
if ($file != "." && $file != "..") {
$this->importfile($path);
}
}
}
protected function importfile($path){
$connection =
sfContext::getInstance()->getDatabaseManager()->getDatabase('doctrine')->getDoctrineConnection();
$connection->beginTransaction();
try {
//more codes here...
while ($data = $reader->read()) //reads each line of a csv file
{
// send the line to another private function to be processed
// and then write to database
$this->writewave($data);
}
$connection->commit();
} catch (Exception $e) {
$connection->rollback();
}
}
脚本的作用基本上是读取a中的所有csv文件 文件夹(每个包含数万行),处理它, 并使用Doctrine的事务将其写入数据库。
虽然我认为我不需要设置内存限制和时间限制 在这两个函数中,脚本退出,因为Doctrine用完所有的 分配1GB内存。
处理10个文件后,通常会停止,并分配更多文件 内存将允许它处理更多的文件,并将仍然 崩溃。
我在这里缺少什么导致记忆没有的东西 处理完每个文件后可以自由使用吗?
Mohd Shakir Zakaria http://www.mohdshakir.net
答案 0 :(得分:4)
尽可能释放任何对象,包括查询/连接对象,尤其是当它们位于循环内时。
答案 1 :(得分:1)
在使用大型数据集时,Doctrine使用了大量的内存 - 以这种方式导入大型/多个文件是不可能的。
即使您在单独的函数调用中导入每个文件,doctrine也有一个内部对象缓存,因此它们不会被释放。
您最好的选择是稍微修改一下任务,因此它接受一个文件名作为参数。如果它被传递,只处理该文件(希望它不会太大)。如果没有传递文件名,它会像现在一样循环遍历所有文件,并通过exec
调用自身,所以它是一个不同的进程,内存真的被释放了。
答案 2 :(得分:0)
我在你的脚本中看到的最大的问题是你经常调用sfcontext。 IMHO sfcontext不是单例,这意味着你在每个循环中创建一个新实例。你不能把连接传递给方法吗?
public function executeImportFile(sfWebRequest $request)
{
ini_set('memory_limit', '1024M');
set_time_limit ( 0 );
$connection = sfContext::getInstance()->getDatabaseManager()->getDatabase('doctrine')->getDoctrineConnection();
//more codes here...
$files = scandir($workspace.'/'.$directory);
foreach ($files as $file) {
$path = $workspace.'/'.$directory.'/'.$file;
if ($file != "." && $file != "..") {
$this->importfile($path, $connection);
}
}
}
protected function importfile($path, $connection){
$connection->beginTransaction();
try {
while ($data = $reader->read()) //reads each line of a csv file
{
$this->writewave($data);
}
$connection->commit();
} catch (Exception $e) {
$connection->rollback();
}
}