我有一個這樣的激活存盤程序:
DECLARE
@conversation_handle [uniqueidentifier],
@message_body [varbinary](max)
WHILE 1 = 1
BEGIN TRY
BEGIN TRANSACTION
WAITFOR
(
RECEIVE TOP (1)
@conversation_handle = [conversation_handle],
@message_body = [message_body]
FROM
[dbo].[my_queue]
), TIMEOUT 1000;
IF @@ROWCOUNT = 0
BEGIN
ROLLBACK TRANSACTION
BREAK
END
SAVE TRANSACTION SavePoint
-- do things
COMMIT TRANSACTION
END TRY
BEGIN CATCH
IF XACT_STATE() = 1
ROLLBACK TRANSACTION SavePoint
IF XACT_STATE() = -1
BEGIN
ROLLBACK TRANSACTION
BEGIN TRANSACTION;
RECEIVE TOP (1)
@message_body = [message_body]
FROM
[dbo].[my_queue]
WHERE
conversation_handle = @conversation_handle
END
-- insert the message to a error log table
END CONVERSATION @conversation_handle
COMMIT TRANSACTION
END CATCH
我的問題:如果這個佇列有多個佇列讀取器,在佇列讀取器 A 回滾事務后,另一個佇列讀取器 B 是否會收到有害訊息,并且鑒于所有訊息都有自己的對話,讀取器 A 無法使用會話句柄接收相同的訊息團體?
uj5u.com熱心網友回復:
在佇列讀取器 A 回滾事務后,另一個佇列讀取器 B 會收到有害訊息嗎?
是的。如果您回滾該訊息在佇列中可供另一個讀者接收,并且您的會話組鎖定將被釋放。
因此,如果您將訊息出列并最終陷入注定失敗的事務或啟用了 XACT_ABORT,您別無選擇,只能完全回滾。再加上與 MultipleActiveResultSets 的不兼容,保存點真的沒有那么有用。
那么該怎么辦?一種選擇是在佇列上打開訊息保留并提交接收。然后在錯誤寫入您的錯誤表。訊息正文將在錯誤表中以及在對話的生命周期中從佇列中通過 SELECT 可用。
或者您可以將 MAX_QUEUE_READERS 設定為 1 以防止并發激活程序使有害訊息出隊。
或者(未經測驗)您可以回滾,并在您的會話擁有獨占Application Lock時重新接收有害訊息,并要求激活程序的初始 RECEIVE 持有相同資源名稱的共享鎖。
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/352323.html
標籤:sql-server 查询语句 服务经纪人
