63971
**現在の処理の流れ(必要項目をPOSTで受信後)**  
・1.DBへINSERT  
・2.該当メールアドレスへ確認メール送信

**発生した問題**  
確認メール送信しようとしたら、エラー発生(SMTP関連)

**質問**  
・この場合のエラー処理はどうすれば良いですか？  
・順番変更して、確認メール送信後DBへINSERTしようかと思ったのですが、万が一DB処理時にエラー発生した場合には整合性が取れなくなってしまいます

**現在の案**  
確認メール送信時にエラー発生したら、DBへINSERTしたデータを(手動ロールバックで)削除するしかないと思うのですが、他に何か良い方法はありますか？  
※削除する理由は、ユーザーが再度登録しようとする際DBにメールアドレスが残っていると一意制約で弾かれるためです
CC BY-SA 4.0
2020-03-19T01:58:17.260
63970
2020-03-19T02:52:16.083
7886
question
php
メールアドレスでユーザーアカウントを登録する際のエラー処理について
SMTPのエラーであれば、PHPでも検知できるでしょう。  
もし、メールのアドレス間違いなどだと即検知はできないので、メールサービスのAPIもしくはログによる検出により復旧かデータの変更対応が必要だと思います。

質問者さんのおっしゃるとおり優先順位はDB→メールでDBの処理が行われてからメールの処理をしたほうが良いと思います。（後述）

データの変更の方法とそれ以外の方法についての質問については  
質問者さんは手動ロールバックを選択していますが、要件によっては再送などの対応で行ける場合もあります。なので  
・手動ロールバック（DELETEか明示的RollBackの実行）  
・テーブルに送信できなかった旨のフラグを用意して、送信できなかった場合はフラグの更新を行い、別途再送処理をする。  
が方法としては挙げられます。  
さらにエラーとなったら一意制約から除外したいということであれば、フラグを「nullありのdatetime」型にしておき、エラーが起きたら日時を挿入するようにして、フラグとメールアドレスのマルチユニークにしておく方法もあるでしょう。

DB→メールがいい理由  
「DBとメール」や「DBとAPI連携」のように  
外部システムとの連携が重なる場合はそれに対するロールバック（障害検知と回復）はその外部システムの障害が起きた場合のそれぞれのリスクとコストを見積もって考えます。

障害のリスクとコストは  
・発生頻度  
・検知  
・堅牢性  
・復旧  
のあたりを確認します。

今回みたいなDBとメールの場合を考えると  
以下のパターンが挙げられます。

  1. DB OK メール OK
  2. DB NG メール OK
  3. DB OK メール NG
  4. DB NG メール NG

１は問題ないとして、  
４は同時に起こることは少ないと思いますが、DBの登録もメールの送信も行われないので、堅牢性は維持されていますが復旧は難しいでしょう。もちろんDBやメール以外にデータを保存すれば復旧は可能ですが、さらに外部システムを増やすとリスクとコストが絡みますのでよく検討してください。

２に関して言えばメールは飛んでいますが、データが存在しないという、システムの辻褄が合わなくなっています。もしこの状態になったときには、障害の検知はできるでしょう。しかし復旧はできますか？メールからデータの復元ができるか？一般的には難しいと思います。

３に関して言えばDBは登録されているのでデータは存在します。がメールが飛ばないので、システム上の不整合が発生しています。検知ができるのであれば、  
前述の通りという形で対応が可能です。

後はどのぐらいの発生頻度とそれを対応するためのコストを見積もって、本当に対応する必要があるかは見極めるべきでしょう。
CC BY-SA 4.0
2020-03-19T02:52:16.083
63971
2020-03-19T02:52:16.083
22665
63970
answer