【发布时间】:2012-10-23 21:55:13
【问题描述】:
我有几个结构如下的存储过程:
USE [WHouse]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE PROCEDURE [dbo].[pr_Alert_Dly]
AS
IF (SELECT LastRunDate FROM WHouse.dbo.AlertRunDates WHERE NameDescription = 'X' ) < (SELECT CONVERT(DATE, GETDATE()))
BEGIN
--================
--need to comment the following out if trying to re-run
UPDATE x
SET x.LastRunDate = CONVERT(DATE,GETDATE())
FROM WHouse.dbo.AlertRunDates x
WHERE [NameDescription] = 'X'
--================
--===============
--DO A LOAD OF STUFF IN HERE
--INCLUDING USING DB_SENDMAIL TO EMAIL 20 PEOPLE
--===============
END
我的同事已经建立了一个报告系统(使用过程/SSIS),该系统每 10 分钟循环一次,只要存储过程完成且没有错误,它就会在控制表中标记为完成。
我不明白的是,即使上面抛出错误,为什么它会在同一批次中多次重复BEGIN / END 之间的部分?
如果防御不够,如何防御我的同事系统导致相同的电子邮件每 10 分钟分发一次?!
【问题讨论】:
-
可能是外部事务被回滚或中止?您可以回滚更新,但不能回滚已发送的电子邮件。也许使用队列表和后台进程而不是立即主动发送电子邮件。
-
@usr 如果是数据库邮件,它是异步的(使用服务代理),所以唯一的风险是你不能回滚它。 :-) 就是说,我同意你的看法。这些电子邮件应该发送到其他地方(无论是 SQL Server 中的后台进程,还是完全外部)。
-
@AaronBertrand - 好的,所以有一个表“EmailQueue”,其中包含
Body、TO、CC等字段,然后(使用代理的经验不多)代理以某种方式检查表,如果它看到新条目,它将运行一个存储过程来构建并使用 DB_SendMail 发送邮件? -
代理将运行一个存储过程来检查表中的新条目,发送它需要的任何电子邮件,然后将条目标记为已处理。有时存储过程将由代理运行,但没有任何要处理的内容。没关系。还有其他方法可以做到这一点(例如服务代理),但代理是迄今为止最简单的。
-
那么这不是一个真正的队列表......您回到了必须等待触发器完成的初始事务。您只是无缘无故地添加了一个附加表。创建代理工作有什么难的?
标签: sql sql-server tsql stored-procedures sql-server-2008-r2