2009-12-31 43 views
1

我有一個cron作業,通過PDF附件發送電子郵件到一個訂閱者列表,每次一個在foreach循環中。我從cron腳本得到了這個消息:Zend_Mail:如何解決PHP致命錯誤:允許的內存大小用盡?

Fatal error: Allowed memory size of 94371840 bytes exhausted (tried to allocate 78643193 bytes) 

我需要做什麼來防止這個錯誤?

而且,我敢肯定,它沒有完成發送給所有用戶,所以我應該如何跟蹤此所以它知道在哪裏再次回升,如果沒有發送給大家?

更新:下面是一個代碼示例:(我使用Zend框架的方式)

public function send(Default_Model_MyEmail $myEmail) 
{ 
    if (null != ($id = $myEmail->attachmentId)) { 
     $file = new Default_Model_File(); 
     $file->find($id); 
     $filepath = APPLICATION_UPLOADS_DIR . '/' . $file->getActualFilename(); 

     $attachment = new Zend_Mime_Part(file_get_contents($filepath)); 
     $attachment->type = $file->getMimeType(); 
     $attachment->disposition = Zend_Mime::DISPOSITION_ATTACHMENT; 
     $attachment->encoding = Zend_Mime::ENCODING_BASE64; 
     $attachment->filename = $file->getDisplayFilename();  
    } 
    $transport = new Zend_Mail_Transport_Smtp('localhost'); 

    $mail = new Zend_Mail('utf-8'); 
    $mail->setFrom('[email protected]', 'From Name'); 
    $mail->setReplyTo('[email protected]'); 
    $mail->setSubject($myEmail->subject); 
    if (isset($attachment)) { 
     $mail->addAttachment($attachment); 
    } 

    $subscribers = $this->getSubscribers(); 
    foreach ($subscribers as $subscriber) { 
     $mail->addTo($subscriber->email); 
     $bodyText = $myEmail->body 
      . "\r\n\r\nIf for any reason you would like to be removed from this mailing list, " 
      . "please visit \r\nhttp://myapp.com/myemail/unsubscribe/email/" 
      . $subscriber->email; 
     $mail->setBodyText($bodyText); 
     $mail->send($transport); 
     $mail->clearRecipients(); 
    } 
} 

更新:我重用$transport變量。我的印象是這是發送給多個用戶的正確方式,但也許這是原因?你怎麼看?

更新:我已經添加了一堆打印內存使用語句的日誌語句,但我現在不知道該怎麼做。內存使用量隨着每封電子郵件而增加用戶列表爲200,則達到160,然後耗盡內存。我該怎麼辦?

回答

0

減少內存使用量,或增加內存限制。

+2

這是一個非常詳細的答覆:-) – 2009-12-31 19:41:04

+3

這是一個非常詳細的問題。 – Malfist 2009-12-31 19:43:01

+0

然而,所有其他的答案提供了一個起點找到一個解決方案... – 2009-12-31 19:53:05

2

它看起來像你的代碼試圖分配基於錯誤信息78MB的一大塊。

檢查你的代碼,任何可能會嘗試在一次分配一個非常大的內存塊。這可能不是由於釋放較小的對象失敗所致,因爲失敗的分配塊很大。

如果您發佈的代碼片段,是造成這一點,我會很樂意去看看,並嘗試進行更詳細的答覆。

至於找出如果你發送給每個人或沒有,你的郵件服務器(SMTP服務器)的檢查寫入日誌發送的消息。如果是這樣,您可以獲得收到電子郵件的人員列表。一般來說,我建議你修改你的PHP代碼,以記錄發送的每封電子郵件的文件或數據庫,以防將來發生崩潰。看到代碼後

編輯:

在表面上,它看起來像一個代表電子郵件和創建連接一次,並重新使用的對象。

我建議你在本地調試代碼。

首先,建立一個與您在生產中所擁有的相同的內存限制。瞭解如何嘗試this resource

然後,在循環中添加一些調試輸出,以查看每次迭代後有多少memory is available

最後,在本地運行代碼,但最好在您的域中替換您的電子郵件地址或已知的錯誤電子郵件地址(這樣您就不會發送垃圾郵件)。隨着您的發送進度,觀看內存使用情況。

這應該有希望幫助您縮小錯誤的原因。

編輯2:

OK,看到內存使用率不斷增長後,有點魔谷歌打開了,這是一個已知的問題與reported workaround

+0

添加了一個代碼示例 – Andrew 2009-12-31 19:50:37

+0

我已經做了你說的,我有一個記錄充滿內存使用情況聲明,但我真的不知道什麼去做。內存使用量隨着每封電子郵件而增加用戶列表爲200,則達到160,然後耗盡內存。 – Andrew 2010-01-01 02:25:29

+0

找到了一個可能的解決方案。請參閱我的答案中的編輯2。 – 2010-01-01 04:33:25

1

除了@ Malfist的回答,您可以:

  • 確保您重用變量代替了循環的每個迭代增加新的。
  • 電子郵件成功發送時系統是否記錄,並在一定數量的電子郵件後停止發送。下一次cron運行時,它應該找出哪些人被髮送並恢復。
1
ini_set("memory_limit","128M"); 
相關問題