2011-08-23 51 views
2

長話短說,如果我打破了一個PHP腳本成微小的塊,我可以最終得到了我所有的代碼運行。不過,我現在有一個腳本,它讀取一個巨大的CSV文件並將每行插入到MySQL數據庫中。每次我想更新我的網站時,不必經歷繁瑣的分割文件的過程,我只想讓這個腳本以我應該知道的方式工作。我的PHP腳本給我500內部服務器錯誤時,他們強烈

我已經得到它之前插入不同的網絡服務器上擁有超過10,000行,但也有至少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"; 

我收到分裂,因爲這個大任務,我很厭倦了。我確信我做錯了很多,因爲我完全是自學成才,一般都會寫意大利麪條,所以不要猶豫。

+0

如果您已經超過了40秒的超時時間,那麼您需要弄清楚爲什麼您的腳本太慢並且可能會做其他事情。我有一個導入大型mysql數據庫的腳本。我用它在3個小時內導入了一個10GB的數據庫。 – desbest

回答

4

要增加的時間限制你的腳本,你將需要編輯虛擬主機配置爲您的網站:

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) 

部分應該提前檢查是否記錄已經存在(如果這樣做,它只是將不會被插入,它會繼續到同樣的效果的忽略下一個)。

+1

刪除檢查重複條目的查詢可以使腳本快速無誤地運行。我想我們現在要做的就是備份桌面,清空它,然後再把整個文件放到一邊。在一個相關的說明,我昨晚做了一個美味的意大利麪條醬... – Kazz

+0

鏈接不工作:( – Nitesh

+0

似乎爲我工作,本來可能是一個暫時的停電? –

3

可以插入使用SQL應減少所花費的時間查詢運行量值的批次(往返可能是你的瓶頸)。

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

很多時候你做巨大的插入這樣,你想這樣做異步,這意味着你轉儲文件的地方,離線處理,然後通知用戶,它的完成,而不是阻礙了頁面加載時間直到完成。

我也看到你在做實際插入操作之前正在檢查存在。您可能需要考慮選擇「可能」匹配的行,然後在PHP端執行檢查(使用散列),而不是每次運行該查詢。

+1

不僅如此,MySQL還能夠直接讀取CSV文件。沒有真正的理由嘗試用PHP編寫它。 – Cfreak

+0

除非您正在編寫導入腳本,該腳本允許用戶爲正在導入的CSV文件設置自己的標題名稱。實際上有十幾個理由有人想用PHP來處理CSV,而不是直接將其提供給數據庫。 – kjdion84

2

看來你已經得到超時在Apache不是PHP。 的set_time_limit功能用於PHP腳本和Apache不知道任何關於它。

相關問題