如何在PHP和MySQL中进行电子邮件事务处理?

时间:2011-01-17 20:01:45

标签: php mysql transactions

我想向我的应用用户发送电子邮件,确保每封电子邮件只发送一次。 我将在数据库中记录电子邮件传输。 如果我使用这个操作顺序:

  1. 插入数据库
  2. 发送电子邮件
  3. 提交
  4. 在发送电子邮件(步骤#2)之后和执行提交之前(步骤#3),脚本有可能超时。在这种情况下,步骤#1中的更改​​将不会被提交,并且电子邮件发送作业将无法知道上次成功发送电子邮件,因此将再次发送相同的电子邮件。

    是否有出路或者我是否需要偶尔使用重复的电子邮件?

4 个答案:

答案 0 :(得分:3)

简而言之:您无法进行电子邮件交易

充其量,您知道您的smtp服务器已收到您发送邮件的请求。但是你无法知道它是被发送,接收还是被退回。

所以,正如您已经建议的那样,最好的选择是偶尔使用重复的电子邮件。无论如何,这将是一个非常罕见的事件。

答案 1 :(得分:2)

你可以使用MySQL事务,基本上它会准备好你的所有查询并在你告诉它时执行它们。

所以你在发送邮件之前准备好查询,然后在发送邮件之后提交它。

更多信息

http://dev.mysql.com/doc/refman/5.0/en/commit.html

或者,您可以将邮件设置为待处理,然后将其更新为已完成。然后运行一个cron作业,该作业会终止已经运行了一段时间的挂起作业,或者尝试重新处理它们。

答案 2 :(得分:1)

您可以制作一个statusenumint,其值为sending, failed, sent_successfully

现在,你这样做:

  1. 在发送邮件之前插入数据。并将status设置为sending
  2. 发送邮件
  3. 根据步骤(2)中的结果,updatefailedsent_successfully
  4. 您可能还希望有一个列tries和一个批处理流程,如果failed,则每30分钟发送一次tries < TRY_THRESHOLD个邮件。然后,将status设置为failed_permanentlysent_successfully并记录错误。

答案 3 :(得分:0)

只是有时间思考我自己的问题。以下是我现在的想法:

有问题的电子邮件发送步骤是:

  1. 插入数据库
  2. 发送电子邮件
  3. 提交
  4. 电子邮件不能成为事务性的,因为步骤#2(上面)不是事务的一部分,即使它是在事务处于活动状态时完成的。

    这些步骤有助于确保重试任何失败的电子邮件发送尝试,但无法保证不会多次发送电子邮件。如果电子邮件发送引擎具有事务感知功能,则只能改善这种情况。这样的引擎会(至少)执行以下操作:

    1. 接受电子邮件作业提交,但在执行提交之前不发送电子邮件
    2. 如果未发送电子邮件,则提交失败。
    3. 如果交易回滚,则取消提交的作业
    4. 我不知道有任何此类电子邮件服务器。

      Nishant,answer建议采取以下步骤:

        
          
      1. 在发送邮件之前插入数据。并将状态设置为发送
      2.   
      3. 发送邮件
      4.   
      5. 根据步骤(2)中的结果,更新行失败或发送成功。
      6.   

      由于脚本超时,这些步骤也无法确保重复发送电子邮件,原因与上述相同。

      到目前为止,我认为,我只需要偶尔使用重复的电子邮件。