SQL代理队列填充两次

时间:2012-10-02 06:54:04

标签: sql-server queue

我正在使用SQL代理执行一些异步任务(在我的情况下发送邮件)。但我遇到的问题是每次将XML消息从触发器传递到队列时,将值插入队列时运行的存储过程将运行两次。

我有一个消息类型:

CREATE MESSAGE TYPE MailMessage
AUTHORIZATION dbo 
VALIDATION = WELL_FORMED_XML

我有合同:

CREATE CONTRACT MailContract
AUTHORIZATION dbo 
(MailMessage SENT BY INITIATOR)

我有一个队列:

    CREATE QUEUE dbo.MessageQueue
WITH STATUS=ON, 
 ACTIVATION ( 
 PROCEDURE_NAME = MailExecuter , 
 MAX_QUEUE_READERS = 1,
 EXECUTE AS OWNER );

我有两项服务:

    CREATE SERVICE MailSendActivator  
AUTHORIZATION dbo  
ON QUEUE dbo.MessageQueue (MailContract) ; // I have removed this the contract to make it a initiator but it did not worked out  

-- Create target Service   
CREATE SERVICE MailSendExec  
AUTHORIZATION dbo   
ON QUEUE dbo.MessageQueue (MailContract);  

这是我的触发器:

 CREATE TRIGGER MailSendTrigOnMailQueue ON dbo.MailQueue
 FOR INSERT 
 As  
 SET NOCOUNT ON;   

DECLARE @MessageBody XML  
DECLARE @TableId int  


SET @MessageBody = (SELECT CreatedDateTime,[Subject], MailType FROM inserted  
FOR XML AUTO)  


If (@MessageBody IS NOT NULL)  
BEGIN  

DECLARE @Handle UNIQUEIDENTIFIER;   
BEGIN DIALOG CONVERSATION @Handle   
FROM SERVICE MailSendActivator   
TO SERVICE 'MailSendExec'   
ON CONTRACT MailContract   
WITH ENCRYPTION = OFF;   

SEND ON CONVERSATION @Handle MESSAGE TYPE MailMessage(@MessageBody);   

END 

我有一个存储过程: 在存储过程中,我将值插入测试表是否存储过程正在运行。

存储过程:

    CREATE PROCEDURE dbo.MailExecuter  
AS   
BEGIN   

DECLARE @msgBody XML    
DECLARE @dlgId uniqueidentifier 
Insert into TestTable(Name, Test) values('MEX','test'); 
WHILE (1 = 1)   
    BEGIN 

            WAITFOR ( RECEIVE TOP(1) @msgBody = CAST(message_body AS XML),     @dlgId = conversation_handle  FROM dbo.MessageQueue ), TIMEOUT 500    
            IF (@@ROWCOUNT = 0 OR @msgBody IS NULL) 
                BEGIN   
                    BREAK   
                END   
            ELSE   
                BEGIN 


                 DECLARE @Subject nvarchar(200), @CreatedDateTime datetime, @MailType nvarchar(50)


                ---EXEC dbo.SendMails 1,1;

                END  
            END CONVERSATION @dlgId

            END  

    END 

但是存储过程运行了两次并填充了我的测试表两次。我认为问题在于触发器中的send conversation部分。

我很长时间都对此深恶痛绝。拜托,有人可以帮助我吗

1 个答案:

答案 0 :(得分:3)

您需要在RECEIVE投影列表中添加message_type_name。当消息类型为MailMessage时,您必须查看收到的消息类型,调用邮件例程。事实上,您将始终收到第二条消息,即END DIALOG中的消息。你只需要在那种情况下再次调用END DIALOG,关闭发送方句柄:

  WAITFOR ( 
      RECEIVE TOP(1) 
         @msgBody = CAST(message_body AS XML),     
         @dlgId = conversation_handle ,
          @msgType = message_type_name
       FROM dbo.MessageQueue ), TIMEOUT 500    
    IF (@@ROWCOUNT = 0 OR @msgBody IS NULL) 
       BREAK   
    ELSE IF @msgType = N'MailMessage'   
    BEGIN 
       DECLARE @Subject nvarchar(200), @CreatedDateTime datetime, @MailType nvarchar(50)
       ---EXEC dbo.SendMails 1,1;
    END  

    END CONVERSATION @dlgId;

你重新发明轮子有什么特别的原因吗?这几乎就是sp_send_dbmail已经有效的方法(除了使用外部激活)。