2012-07-31 132 views
1

當用戶在我的網站上註冊時,我使用email_sent ='NO'在數據庫中創建了一個用戶記錄。然後,我有一個每隔幾分鐘發送一封歡迎郵件的cron作業。它選擇email_sent ='NO'併發送歡迎郵件的所有用戶記錄。如何在發送電子郵件後提交「發送電子郵件」操作時避免發送重複電子郵件?

如果郵件發送成功,它會將用戶記錄更新爲email_sent ='YES'。我的問題是,如何避免電子郵件發送成功但用戶記錄更新失敗的情況,並在下一次運行cron作業時發送重複的電子郵件。即使我使用了數據庫事務,並且在發送電子郵件之前更新了記錄,但之後又提交了,如果提交失敗,我將遇到重複發送電子郵件的情況。

另一種方法是將記錄更新爲email_sent ='YES'並立即提交,然後嘗試發送電子郵件。但是,如果電子郵件發送失敗,則不會發送電子郵件。

有沒有什麼辦法可以確保一次發送電子郵件?我意識到由於一些外部因素,電子郵件傳遞最終可能會失敗,但我只是想確保我的SMTP服務器成功將其關閉一次。

+0

爲什麼用戶記錄的更新失敗?解決這個問題,你已經解決了你的問題。 – 2012-07-31 21:13:53

+0

您使用的是什麼RDBMS,Oracle,SQL-Server,MySQL等?可能會有一些特定於數據庫的內容可以提供幫助。 – Ben 2012-07-31 21:14:29

+0

除了Robert Harvey的評論之外 - 如果在更新已發送記錄時提交失敗,那麼可以做的很少,以防止重複。如果cron依賴於數據庫中的值,則該值必須可靠地更新。否則,你將不得不開發更復雜的方法來處理不一致的數據。 – Farray 2012-07-31 21:17:54

回答

1

你的評論指出,提交沒有失敗,所以你可能會擔心風。

保留交易儘可能的小,並有它失敗無論怎樣在你的系統更容易接受...

BeginTransaction; 
LookupRecord; 

SendMail; 

if(SentSuccessfully) 
{ 
    UpdateRecord(Sent=True); 
    CommitTransaction; 
} 
else 
{ 
    RollbackTransaction; 
} 

另外,您可以用更多的複雜性和不繞電子郵件功能的交易做到這一點,但我沒有更好的看到這一點:

BeginTransaction; 
LookupRecord; 
UpdateRecord(Sent=True); 
CommitTransaction; 

SendMail; 

if(!SentSuccessfully) 
{ 
    UpdateRecord(Sent=False); 
} 

無論哪種方式,如果有錯誤和正確的值不會提交到數據庫中,有沒有什麼可以做,以避免它不引入(可能不必要)複雜性。你真的應該專注於使更新&事務穩定,所以它不會失敗更新。