2012-11-27 26 views
0

以下存儲過程由我們的代理每5分鐘運行一次 - 它使用此proc掃描表Control_EmailQueue以查看是否有任何新電子郵件發送出去。爲什麼此過程會生成兩個電子郵件?

我想測試當不正確的電子郵件信息輸入表Control_EmailQueue時,過程如何表現。下面詳細介紹兩項測試及其結果。

TEST1
我將記錄添加到Control_EmailQueue這在所有3場EmailTO/EmailCC and EmailBCCNULL條目。這工作正常,即和錯誤被捕獲並執行內部CATCH的代碼,所以我收到題爲'ERROR OCCURED DURING EMAIL CREATION'

TEST2
我將記錄添加到Control_EmailQueue的電子郵件。在字段EmailTO中輸入該字符串'[email protected]; [email protected]',即第一個電子郵件地址有效,但第二個電子郵件地址是無效。當代理運行程序時,收到的電子郵件是[email protected],但接着半秒鐘後收到另一個相同的電子郵件[email protected]。由於未收到標題爲'ERROR OCCURED DURING EMAIL CREATION'的電子郵件,因此CATCH代碼未在此測試中執行。

BEGIN TRY 

    DECLARE @Exit TINYINT = 0 
    WHILE @Exit = 0 
     BEGIN 

     BEGIN TRANSACTION 

      DECLARE @MailIdFound INT = 
      (
      SELECT 
        CASE 
          WHEN MIN([EmailId]) IS NULL THEN 0 
          ELSE MIN([EmailId]) 
        END 
      FROM [xxx].[console].[Control_EmailQueue] 
      WHERE 
        [DateInsertKey] IS NOT NULL 
        AND 
         (--the following gives option to re-run past mails by updating DateEmailKey to NULL 
         [DateEmailKey] IS NULL 
         OR 
         [DateEmailKey] < [DateInsertKey] 
         ) 
        AND 
        ErrorOccured = 0 
        AND 
        EmailActive = 1 
      ) 

      IF @MailIdFound = 0 
      BEGIN SET @Exit = 1 END --exit here as 
      ELSE 

      BEGIN --send the mail here 

        --DECLARE @EmailId INT 
        DECLARE @DateInsertKey INT 
        DECLARE @DateEmailKey INT 
        DECLARE @CallingReportName NVARCHAR(1000) 
        DECLARE @EmailBCC NVARCHAR(1000) 
        DECLARE @EmailTO NVARCHAR(1000) 
        DECLARE @EmailCC NVARCHAR(1000) 
        DECLARE @EmailBody NVARCHAR(MAX) 
        DECLARE @EmailAttachmentPath NVARCHAR(1000) 
        DECLARE @EmailImportance VARCHAR(6) 
        DECLARE @EmailSubject NVARCHAR(1000) 

        ;WITH myMostUrgentMail_cte 
        AS 
          (
          SELECT 
            TOP 1 
            --[EmailId], 
            [DateInsertKey], 
            [DateEmailKey], 
            [CallingReportName], 
            [EmailBCC], 
            [EmailTO], 
            [EmailCC], 
            [EmailBody], 
            [EmailAttachmentPath], 
            [EmailImportance], 
            [EmailSubject] 
          FROM [xxx].[console].[Control_EmailQueue] 
          WHERE [EmailId] = @MailIdFound 
          ) 
        SELECT 
          @DateInsertKey   = [DateInsertKey], 
          @DateEmailKey   = [DateEmailKey], 
          @CallingReportName = [CallingReportName], 
          @EmailTO     = [EmailTO],   
          @EmailCC     = [EmailCC],       
          @EmailBCC    = [EmailBCC], 
          @EmailBody    = [EmailBody], 
          @EmailAttachmentPath = [EmailAttachmentPath], 
          @EmailImportance  = CASE 
                       WHEN [EmailImportance] = 0 THEN 'Low' 
                       WHEN [EmailImportance] = 1 THEN 'Normal' 
                       WHEN [EmailImportance] = 2 THEN 'High' 
                    END, 
          @EmailSubject   = [EmailSubject] 
        FROM myMostUrgentMail_cte 


        SET @EmailBody = @EmailBody + '<b>Please contact us with any questions</b></p></span></html>' 
        EXEC msdb..sp_send_dbmail 
          @recipients      = @EmailTO, 
          @copy_recipients   = @EmailCC, 
          @blind_copy_recipients = @EmailBCC, 
          @subject       = @EmailSubject, 
          @file_attachments   = @EmailAttachmentPath, 
          @Importance     = @EmailImportance, 
          @body_format     = 'html', 
          @body        = @EmailBody  

        UPDATE x 
        SET 
           x.[DateEmailKey]  = (CONVERT(CHAR(8),GETDATE(),(112))), 
           x.[DateEmailTime] = (CONVERT([time](7),left(CONVERT([char](12),GETDATE(),(114)),(8)),(0))) 
        FROM [xxx].[console].[Control_EmailQueue] x 
        WHERE x.[EmailId] = @MailIdFound 

      END 

     COMMIT TRANSACTION 

     END 

END TRY 



BEGIN CATCH 

    IF @@trancount>0 
     BEGIN 
       ROLLBACK TRANSACTION 
     END 

    -- handle error here 
    DECLARE @ErrorMessage VARCHAR(100) = '<html><p>Error occured during creation of EmailId: ' + CONVERT(VARCHAR(10),@MailIdFound) + '</p><p>xxx.console.Control_EmailQueue</p></html>' 
    EXEC msdb..sp_send_dbmail 
      @recipients = '[email protected];' 
      , @subject = 'ERROR OCCURED DURING EMAIL CREATION' 
      , @body_format = 'html' 
      , @body = @ErrorMessage 

    UPDATE x 
    SET x.ErrorOccured = 1 
    FROM [xxx].[console].[Control_EmailQueue] x 
    WHERE x.[EmailId] = @MailIdFound 

END CATCH; 
END 
+2

我發現這非常難以遵循。 '所以它有我的正確地址加上明顯不正確的地址' - 在同一列/行?這怎麼可能? '然後我收到消息' - 哪條消息? –

+0

如果你擺脫了交易,問題是否消失? – UnhandledExcepSean

+0

@AaronBertrand - 我現在編輯操作系統 – whytheq

回答

1

該問題似乎與交易時間有關。通過在提交之後添加延遲,事務能夠在下一個循環執行之前完成並提交。

你應該做的一件事是從sp_send_dbmail獲得mailitem_id。也許你是正確的,它是失敗的,但沒有錯誤,但這不應該影響交易。我唯一能想到的是,你正在變髒或幻影讀取,因爲事務實際上還沒有提交,所以小延遲允許數據實際提交。

+0

我不知道第一封郵件什麼時候發送,一封電子郵件被髮回說xxxxxxxx @ xxxxxxx是無效郵件?不知道如果我能夠捕獲這個錯誤信息並將其轉發給我自己? – whytheq

+0

我已經使用了你的初步評論到OP,剛從'STORED PROCEDURE'中刪除'TRANSACTION' ....添加DELAY'是更多的解決方法,而不是生產過程的很好實踐 – whytheq

相關問題