我的PHP脚本给我500内部服务器错误时,他们是激烈的


My PHP scripts give me 500 Internal Server Error when they're intense

长话短说,如果我把PHP脚本分解成小块,我最终可以让我的所有代码运行。但是,我现在有一个脚本,它读取一个巨大的CSV文件并将每一行插入到MySQL数据库中。每次我想更新我的网站时,我都要经历拆分文件的繁重过程,而不是每次都要经历拆分文件的繁重过程,我只是想让这个脚本按照我知道它应该的方式工作。

我已经得到它插入大约10,000行之前在不同的web服务器上,但至少有7倍,在文件中,它在它完成之前崩溃。

所以,故事是,在一个服务器上,它在应该停止之前停止,而在另一个服务器上,它根本没有运行…它只会在30秒后发出500个错误。

Apache错误日志告诉我,当脚本死亡时,以下几行:

[Tue Aug 23 13:09:04 2011] [warn] [client 71.168.85.72] mod_fcgid: read data timeout in 40 seconds
[Tue Aug 23 13:09:04 2011] [error] [client 71.168.85.72] Premature end of script headers: newcsvupdater.php

我在脚本的顶部有这两行:

set_time_limit(0);
ini_set('memory_limit','256M');

,因为之前我有一个致命的内存分配错误,因为显然将一个大文件分割成数组是内存密集型的。

插入代码:

$file = "./bigdumbfile.csv";  // roughly 30mb
$handle = fopen($file, r);
$firstentry = 0;
while($csv = fgetcsv($handle))
{
    if($firstentry == 0)
    {
        $firstentry++;  // skips the top row of field names
    }
    else
    {         
      // unimportant conditional code omitted
        $checkforexisting = mysql_query("SELECT * FROM DB_TABLE WHERE ".
                "id_one = '".$csv[0]."' AND id_two = '".$csv[2]."'");
        $checknum = mysql_num_rows($checkforexisting);
        if($checknum == 0)
        {
            if(!mysql_query("INSERT INTO DB_TABLE ".
                       "(id_one, data_one, id_two, data_two, ".
                        /* so on for 22 total fields */") 
              VALUES ('".addslashes($csv[0])."', '".
                         addslashes($csv[1])."', '".
                         addslashes($csv[2])."', '".
                         addslashes($csv[3])."' "/* ditto, as above */))
            {                    
                exit("<br>" . mysql_error());
            }
            else
            {
                print_r($csv);
                echo " insert complete<br><br>";
            } 
        }            
    }
}        
echo "<br><b>DB_TABLE UPDATED"; 

我以前因为这个不得不把大的任务分开,我已经厌倦了。我敢肯定我做错了很多,因为我完全是自学的,通常写的都是意大利面条,所以请不要保留。

要增加脚本的时间限制,您需要为您的站点编辑虚拟主机配置:

http://www.moe.co.uk/2009/08/17/php-running-under-mod_fcgid-read-data-timeout-in-40-seconds-on-plesk/

(mod_fcgid的超时覆盖PHP的超时)

要使您的脚本更快(因此您可能不需要执行上述步骤,这在共享主机上可能不可能),请尝试以下操作:

提前准备要插入的所有信息以进行批量插入。查询应该看起来像这样:

INSERT IGNORE INTO (id_one, data_one, id_two, data_two) VALUES
(1, 'apple', 3, 'banana'),
(4, 'pear', 5, 'orange)

IGNORE部分应该具有相同的效果,即提前检查记录是否已经存在(如果存在,则不会插入该记录,而是继续插入下一个记录)。

您可以使用SQL插入批量值,这应该会减少查询运行的时间(往返可能是瓶颈)。

INSERT INTO table (cola,colb...)
VALUES
  (vala,valb...),
  (valc,vald...)

大多数时候,当你做这样的大插入时,你想要异步地做它,这意味着你把文件转储到某个地方,离线处理它,然后通知用户它已经完成了,而不是让页面加载直到完成。

我还看到你在插入之前做了一个存在性检查。您可能需要考虑选择"可能"匹配的行,然后在PHP端执行检查(使用散列),而不是每次都运行该查询。

似乎你在Apache上超时了,而不是在PHP上。Set_time_limit函数用于php-script, apache不知道它

我的第一反应是不用PHP使用mysqlimport或更好的LOAD DATA INFILE来完成所有这些。

LOAD DATA INFILE ./bigdumbfile.csv INTO TABLE tbl_name;