- PR -

メール送信処理とDB更新処理を1つのトランザクションにするには

1
投稿者投稿内容
serious
常連さん
会議室デビュー日: 2001/08/22
投稿数: 31
投稿日時: 2003-11-30 12:41
ご相談です。
メール送信処理(SmtpMail)とDB更新処理(ストアド)を1つのトランザクションにするには
どうすればよいでしょうか?
メール送信処理が成功したら、DB更新処理を行うようにした場合
DB更新処理が失敗するとメールを止めることは出来ません。
その逆の場合、メールが飛んでいるにもかかわらず、DBは更新されません。
このような場合、どうするのがベストでしょうか?

ASP.NET(C#)SQLServer2000
なちゃ
ぬし
会議室デビュー日: 2003/06/11
投稿数: 872
投稿日時: 2003-11-30 13:09
引用:

seriousさんの書き込み (2003-11-30 12:41) より:
メール送信処理が成功したら、DB更新処理を行うようにした場合
DB更新処理が失敗するとメールを止めることは出来ません。
その逆の場合、メールが飛んでいるにもかかわらず、DBは更新されません。


可能性で言えば、DBのコミット前にメール送信して、DB側のコミットまたはロールバックで対応するのが「まし」な気がしますが、どちらにしても完全には出来ないかな。

私はやった事ないですが、例えばMQとか分散トランザクション出来るキューを使ってトランザクションを共有するとか(うまく出来るのか、ここまでやるのかというのはあるかも)。
あるいは、特定のフォルダにメールファイル等を置く事で、キューのような使い方が出来るメールサーバの機能を使うとか。

ただ、メール送信というのは本質的に、即時で送信が成功かは分からないので(大元のSMTPサーバとの処理の成否は分かるとしても)、この辺りをどう考えるかというのがあると思います。

# 余り詳しくないので他の方の意見を参考にした方がいいかも…
プリンス
ベテラン
会議室デビュー日: 2003/07/05
投稿数: 78
お住まい・勤務地: 神奈川
投稿日時: 2003-11-30 13:32
具体的にどういった業務処理か分かりませんが、
例えば受注処理とその受注確認メールであるとすると、

Begin
SPで受注処理

if (正常終了) {
DBコミット
受注確認メール送信
エラーメールの再送処理 (ここは別スレッドで2、3回リトライする)
}else{
DBロールバック
}


がよいのでは?
基本的にメール送信をロールバックすることは出来ないため、
トランザクションに参加させることは出来ないような気がしますが。


[ メッセージ編集済み 編集者: プリンス 編集日時 2003-11-30 13:34 ]
serious
常連さん
会議室デビュー日: 2001/08/22
投稿数: 31
投稿日時: 2003-11-30 14:10
私も、sqlTransactionの中にメール送信処理を入れちゃおーかな・・・
なんてことも考えましたが、怖いのでやめました。
それでは、どっちが先の方が良いか?という質問ではいかがでしょうか?
メール送信処理の成否はSMTPサーバとの処理の成否でかまいません。
ron
常連さん
会議室デビュー日: 2002/08/19
投稿数: 46
投稿日時: 2003-11-30 16:32
プリンスさんの言うように具体的な業務処理が分からないと
何ともいえないような気もしますが、
メールの送信が確実に行われても、確実に閲覧されるかは別問題ですよね。
そういう意味で
1.DBはとりあえず更新フラグでも立てておく(仮更新)
2.送信メールに閲覧確認のURLを入れてメール送信
3.閲覧者がメールのURLをクリック
4.URLで指定したプログラムでDBをあらためて更新
なんてどうですか?

 まあ後はメール送信エラー時のリプライアドレスを設定しておいて、
あとでそこにたまったエラーメールを取り出してDBを更新する
プログラムを作るとか。
メールの場合、数日後にエラーメールとして帰ってくることも
あるので、いずれにしろ確実に1トランザクションとする事は難しいですね。
serious
常連さん
会議室デビュー日: 2001/08/22
投稿数: 31
投稿日時: 2003-11-30 17:26
皆さんありがとうございます。
Webでワークフローを作ってました。
解決方法としましては、ASPで受信箱(DBの中身を表示する)を作って、
もしメールがダメでも、その受信箱にはメールが来ているみたいな感じに仕上げてみました。
結構メールを送信する場合、それに伴いDBにも書込むことが多いので
ちょっと皆さんの意見を聞いてみました。
ありがとうございました。
Jitta
ぬし
会議室デビュー日: 2002/07/05
投稿数: 6267
お住まい・勤務地: 兵庫県・海手
投稿日時: 2003-11-30 19:59
 今、メールというと電話に変わる即時応答に使われていますが、本来は郵便と同じく、『いつ届くかわからない』ものです。これは、HTTPの仕組みと同じ・・・同じインフラ上に構築されているので、同じように考えてよいでしょう。また、送信元のサーバにエラーが返ってこなかったからと言って、メールの送信が成功したともいえないかもしれません。また、メールが送信できたからと言って、メールの『内容が伝わった』ともいえません。これは、スパムメールに分類されたり、長い間未読で放っておかれてサーバの処理で削除されてしまったり、etc...ということもあり得るからです。

 まぁ、そういうレアケースは今回考えなくてもいいのでしょうが。

 それで、メールの送信とデータベースの更新を確実に同期させたいなら、テンポラリ表を用意し、メールの中にウェブサービスへアクセスするリンクを書き、ウェブサービスでテンポラリから本テーブルへ書き写す、という処理が考えられます。

 まぁ、そこまでしなければならないものか、考える余地はありますが。

 結局、『メールの送信』と、『データベースの更新』の、どちらが重要かと言うところにあるのではないでしょうか。これらは全く違うものによって実行されますから、同じトランザクションで管理はできないでしょう。
1

スキルアップ/キャリアアップ(JOB@IT)