我们的代理每隔5分钟运行以下存储过程 - 它使用此过程扫描表Control_EmailQueue
以查看是否有任何新的电子邮件要发送。
我想测试在表Control_EmailQueue
中输入错误的电子邮件信息时proc的行为方式。两项测试及其结果详述如下。
TEST1
我向Control_EmailQueue
添加了一条记录,该记录在所有3个字段NULL
中都有EmailTO/EmailCC and EmailBCC
个条目。这很好,但错误被困,CATCH
中的代码被执行,因此我收到一封标题为'ERROR OCCURED DURING EMAIL CREATION'
的电子邮件
TEST2
我向Control_EmailQueue
添加了一条记录。在字段EmailTO
中,我输入此字符串'me@me.co.uk; xxxxxxx@xxxxx'
,即第一个电子邮件地址有效,但第二个电子邮件地址无效。当代理运行该过程时,me@me.co.uk
会收到一封电子邮件,但是半秒后,me@me.co.uk
会收到另一封相同的电子邮件。由于未收到标题为CATCH
的电子邮件,因此未在此测试中执行'ERROR OCCURED DURING EMAIL CREATION'
代码。
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 = 'me@me.co.uk;'
, @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
答案 0 :(得分:1)
问题似乎与交易时间有关。通过在提交后添加延迟,事务能够在下一个循环执行之前完成并提交。
您应该做的一件事是从sp_send_dbmail获取mailitem_id。也许你是正确的,它是失败的,但没有错误,但这不应该影响交易。我唯一能想到的是你得到了脏或幻读,因为事务实际上还没有提交,所以小延迟允许实际提交数据。