当大量数据批量写入文件时,php脚本内存不足

当大量数据批量写入文件时,php脚本内存不足,php,batch-processing,fwrite,Php,Batch Processing,Fwrite,我的脚本在运行我们的内存时不断出现问题 我需要脚本在数据库中循环遍历每个客户,然后获取所有产品数据并生成一个文本文件。每个客户可以拥有1到100000种产品 我以1000个为一批拿出产品数据,并写入一个文件,试图阻止脚本超时。这已经改善了很多,但是,我仍然与拥有大量产品的客户有问题。它似乎与拥有5000多种产品的客户存在问题 在第五批(5000个产品)之后,它似乎停止写入文件,但浏览器只是挂起,好像它仍在生成文件,但文件中的产品编号从未增加 有人能帮忙吗 set_time_limit(0);

我的脚本在运行我们的内存时不断出现问题

我需要脚本在数据库中循环遍历每个客户,然后获取所有产品数据并生成一个文本文件。每个客户可以拥有1到100000种产品

我以1000个为一批拿出产品数据,并写入一个文件,试图阻止脚本超时。这已经改善了很多,但是,我仍然与拥有大量产品的客户有问题。它似乎与拥有5000多种产品的客户存在问题

在第五批(5000个产品)之后,它似乎停止写入文件,但浏览器只是挂起,好像它仍在生成文件,但文件中的产品编号从未增加

有人能帮忙吗

set_time_limit(0);

$db = new msSqlConnect('db');

$select = "SELECT customer FROM feeds ";

$run = mssql_query($select);

while($row = mssql_fetch_array($run)){
    $arg = $row['customer'];
    $txt_file = 'shopkeeper/'. $arg . '.txt';   
    $generated = generateFeed($db, $arg, $txt_file);

    if ($generated){
        $update = "UPDATE feeds SET lastGenerated = '$generated' WHERE customer = '$arg' ";
        mssql_query($update);
    }

}

function generateFeed($db, $customer, $file){
    //if file already exists then delete file so can write new file
    if (file_exists($file)){
        unlink($file);
    }   

    $datafeed_separator = "|";

    //get product details       
    $productsObj = new Products($db, customer)

    //find out how many products customer has
    $countProds = $productsObj->countProducts();

    $productBatchLimit = 1000;          

        //create new file
    $fh = fopen($file, 'a');

    $counter = 1;

    for ($i = 0; $i < $countProds; $i += $productBatchLimit) {

        $txt = '';

        $limit = $productBatchLimit*$counter;

        $products = $productsObj->getProducts($i, $limit);      

            foreach($products as $product){

                    $txt .=   
                    $prod_name . $datafeed_separator . 
                    $prod_brand . $datafeed_separator . 
                    $prod_desc . $datafeed_separator .
                    $prod_price . $datafeed_separator . "\n";   
                }
            }   

        fwrite($fh, $txt);
        flush();
        $counter++;     
    }
    fclose($fh);

    $endTime = date('Y-m-d H:i:s');

    return $endTime;
}
设置时间限制(0);
$db=新的msSqlConnect('db');
$select=“从源中选择客户”;
$run=mssql\u查询($select);
while($row=mssql\u fetch\u数组($run)){
$arg=$row['customer'];
$txt_file='shopkeeper/'.$arg..txt';
$generated=generateFeed($db、$arg、$txt\u文件);
如果生成($){
$update=“update feeds SET lastGenerated='$generated',其中customer='$arg';
mssql_查询($update);
}
}
函数generateFeed($db、$customer、$file){
//若文件已经存在,则删除文件,以便可以写入新文件
如果(文件_存在($file)){
取消链接($文件);
}   
$datafeed_separator=“|”;
//获取产品详细信息
$productsObj=新产品($db,客户)
//了解客户拥有多少产品
$countProds=$productsObj->countProducts();
$productBatchLimit=1000;
//创建新文件
$fh=fopen($file,'a');
$counter=1;
对于($i=0;$i<$countProds;$i+=$productBatchLimit){
$txt='';
$limit=$productBatchLimit*$counter;
$products=$productsObj->getProducts($i,$limit);
foreach($products as$product){
$txt.=
$prod\u name.$datafeed\u分隔符。
$prod_品牌。$datafeed_分离器。
$prod_desc.$datafeed_分隔符。
$prod_价格。$datafeed_分隔符。“\n”;
}
}   
fwrite($fh,$txt);
冲洗();
$counter++;
}
fclose($fh);
$endTime=日期('Y-m-d H:i:s');
返回$endTime;
}

我发现有一件事可能对您的内存使用有所帮助。如果在foreach循环内移动fwrite(),则也可以在循环内释放$txt。所以它会是这样的:

foreach($products as $product){
  $txt =   
  $prod_name . $datafeed_separator . 
  $prod_brand . $datafeed_separator . 
  $prod_desc . $datafeed_separator .
  $prod_price . $datafeed_separator . "\n";  

  fwrite($fh, $txt);
}

如果您有许多产品,这将防止$txt变大。

也许您最好不要从浏览器运行此脚本,而是从命令行运行此脚本?是的,我也尝试过此方法,其行为完全相同。对于CLI,超时应硬编码为
0
,即从不超时。您是否收到错误消息?你查过日志了吗?是的,对不起,是内存不足,不是时间。我没有错,那是个错误。当内存耗尽时,它不是“超时”。您需要在代码中观察内存使用情况。释放未使用的结果集等。使用调试器/探查器查看超出限制的地方。也许您的
内存\u限制
太小,您的脚本无法完成。一次只能向$txt添加1000个产品,然后将其写入文件,因此我认为这不会导致内存问题,为什么只有在5000个产品之后才会成为问题?