1

ユーザーが私の Web サイトにサインアップすると、データベースに email_sent = 'NO' のユーザー レコードが作成されます。次に、数分ごとにウェルカム メールを送信する cron ジョブがあります。email_sent = 'NO' であるすべてのユーザー レコードを選択し、ウェルカム メールを送信します。

電子メールが正常に送信されると、ユーザー レコードが email_sent='YES' に更新されます。私の質問は、電子メールは正常に送信されたが、ユーザー レコードの更新が失敗し、次に cron ジョブが実行されたときに重複した電子メールが送信されるというシナリオをどのように回避できるかということです。データベース トランザクションを使用し、メールを送信する前にレコードを更新し、後でコミットしたとしても、コミットが失敗すると、重複したメールが送信されるという同じ状況になります。

別の方法は、レコードを email_sent='YES' に更新してすぐにコミットしてから、電子メールの送信を試みることです。しかし、電子メールの送信が失敗した場合、電子メールは送信されません。

電子メールの送信が 1 回だけであることを保証する方法はありますか? 電子メールの配信は、多くの外的要因により最終的に失敗する可能性があることを認識していますが、SMTP サーバーが確実に 1 回だけ配信を成功させたいだけです。

4

1 に答える 1

1

あなたのコメントは、コミットが失敗していないと述べているので、あなたは風を心配しているかもしれません.

トランザクションをできるだけ小さく保ち、システムでより受け入れられる方法で失敗させます...

BeginTransaction;
LookupRecord;

SendMail;

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

別の方法として、より複雑で、電子メール機能に関するトランザクションなしでそれを行うこともできますが、私はこれが良いとは思いません:

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

SendMail;

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

いずれにせよ、エラーがあり、正しい値がデータベースにコミットされていない場合は、(不要な可能性がある) 複雑さを導入せずにそれを回避するためにできることはあまりありません。更新に失敗しないように、更新とトランザクションを確実に行うことに集中する必要があります。

于 2012-07-31T21:24:24.327 に答える