【发布时间】:2012-04-21 21:12:06
【问题描述】:
我在两个不同的实例上实现了许多 SSB。它们是基于异步触发器的数据推送模式。
我的SQL Info如下图: Microsoft SQL Server 管理工作室 10.50.2500.0 Microsoft 分析服务客户端工具 10.50.2500.0 Microsoft 数据访问组件 (MDAC) 6.1.7601.17514 微软 MSXML 3.0 4.0 5.0 6.0 微软 Internet Explorer 9.0.8112.16421 微软 .NET 框架 2.0.50727.5448 操作系统 6.1.7601
我的场景主要如下图所示
-
多条记录被插入为批量在表中或一条记录。
此数据被发送到另一个数据库。
激活过程开始在 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 并将其从 Receive and Process 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
【问题讨论】:
标签: sql-server-2008 service-broker