我正在实施许多在两个不同实例上工作的 SSB。它们是基于异步触发器的数据推送模式。
我的SQL 信息如下所示: Microsoft SQL Server Management Studio 10.50.2500.0 Microsoft Analysis Services Client Tools 10.50.2500.0 Microsoft Data Access Components (MDAC) 6.1.7601.17514 Microsoft MSXML 3.0 4.0 5.0 6.0 Microsoft Internet Explorer 9.0.8112.16421 Microsoft .NET Framework 2.0.50727.5448 操作系统 6.1.7601
我的场景主要如下图
多条记录作为Bulk in table 或One Record插入。
该数据被发送到另一个数据库。
激活过程在 BEGIN TRAN 和 END TRAN 之间开始。
它验证此消息。
如果验证不成功,则应从队列中删除此消息,并将ACk发送回,因为该消息使用不同的 SSB 对象无效。
否则,将发送ACK消息,因为消息已成功读取。
然后,激活过程调用另一个过程来处理消息体。
这个 USP_Process_Records 也在BEGIN TRAN 和 END TRAN 之间。
由于很多原因,根据我的某些业务需求,此过程可能会失败。
要么是 Pro SQL Server 2008 Service Broker。
所以在激活过程中,它要么进入 USP_Process_Records 的失败状态,要么进入 BEGIN CATCH 部分并回滚事务并发送失败 ACK。
最后发现前面的read success ack根本没有发送,第二个发送正常。
所以我对 Broker Service 中的事务管理感到非常困惑。
我应该对每个单独的任务使用 BEGIN TRAN 并将其从接收和处理 UPS 中删除吗?
我是否也应该在 USP_Process_Records 中使用 TRY、CATCH 并将错误返回给 USP_Receive_Records?
我是否应该修改我的 TRY、CATCH 块 ar Receive 以避免此问题
最后,我希望即使之后出现问题也能发送所有确认,并希望完全避免 Poison 消息和回滚。提前致谢。
-顺便说一句,我使用 rusanu 博客进行代理服务错误处理并阅读 Pro SQL Server 2008 Service Broker 事务管理部分。
查找以下 USP 示例。
--USP_Receive_Records
BEGIN TRY
BEGIN TRAN
WHILE 1=1
BEGIN
SELECT @ReplyMessage = NULL, @TargetDlgHandle = NULL
WAITFOR (RECEIVE TOP(1)
@TargetDlgHandle=Conversation_Handle
,@ReplyMessage = CAST(message_body AS XML)
,@ReplyMessageName = Message_Type_Name
FROM Q_Service_Receive), TIMEOUT 1000
IF @TargetDlgHandle IS NULL
BREAK
--Check if the message has the same message type expected
IF @ReplyMessageName=N'Service_Msg'
BEGIN
--Send Batch Read Success ACK
--Send ACK Here
EXEC [dbo].[USP_ACKMsg_Send] @ACKMsg, @Service_Msg;
--Handle ACK Send failed!
-- Execute the USP_Service_Msg_Process for the batch rows
EXECUTE USP_Service_Msg_Process @ReplyMessageName, @RC OUTPUT;
--Case Processing Succeeded
IF @RC=0
BEGIN
--Send Batch Read Success ACK
END
--SEND ACK Processing failed with Return Code to define cause of the error
ELSE
BEGIN
--Send Batch Processing Failed ACK
END
END
END CONVERSATION @TargetDlgHandle;
END
COMMIT TRAN;
END TRY
BEGIN CATCH
if (XACT_STATE()) = -1
BEGIN
rollback transaction;
END;
if (XACT_STATE()) = 1
BEGIN
DECLARE @error int, @message nvarchar(4000), @handle uniqueidentifier;
SELECT @error = ERROR_NUMBER(), @message = ERROR_MESSAGE();
END conversation @handle with error = @error description = @message;
COMMIT;
END
END CATCH
END
--USP_Process_Records
BEGIN TRAN
While(@nCount <= @nodesCount)
BEGIN
IF(@S_HIS_Status = '02')
BEGIN
-- check N_Paid_Trans_ID is not nuul or zero or empty
IF( @N_GET_ID IS NULL OR @N_GET_ID = 0 OR @N_GET_ID = '')
BEGIN
SET @RC = 8
RETURN;
END
EXECUTE USP_Handle_Delivered_Service @N_GET_ID, @RC OUTPUT
SELECT @myERROR = @@ERROR--, @myRowCount = @@ROWCOUNT
IF @myERROR <> 0 OR @RC <> 0
BEGIN
ROLLBACK TRAN
END
END
--A lot of similar cases
END TRAN