2009-09-30 70 views
2

我有一個將消息放入SQL Server Service Broker消息隊列的存儲過程。如果出現錯誤並且消息未放置在消息隊列中,我需要從存儲過程返回錯誤消息。我看到的問題是,即使SQL Server Service Broker被禁用(這是我如何測試失敗將消息放入隊列中),當我運行TSQL代碼時,它不會返回錯誤隊列中的消息。SQL Server Service Broker錯誤處理

有誰知道如何檢測是否在SQL Server Broker消息隊列中放置消息失敗?

回答

19

Service Broker不會將消息放入目標隊列中。而是放入數據庫傳輸隊列(sys.transmission_queue)。發送完成後,消息由後臺發送器接收,路由解析並將消息發送到目標。

如果目的地碰巧位於同一個實例則SEND語句本身,其中,所述消息被放入直入目標隊列期間嘗試的快捷方式輸送路徑內。如果排隊失敗,則該消息被反彈並放置在正常遞送路徑中,即,放入sys.trasnmission_queu e。消息卡在sys.transmission_queue將有一個transmission_status解釋爲什麼消息無法傳遞。系統將自動重新嘗試這些消息。

當SEND可以返回一個錯誤的唯一情況是當消息不能發送,而不是當它不能交付。如果您在關閉的對話中嘗試登錄SEND,或者如果有一些非Broker錯誤(只讀數據庫,記錄已滿,內存不足等),即使接受sys.transmission_queue也無法接收郵件。

macking甚至本地投遞異步的這種行爲和鬆散耦合是故意的,旨在通過行爲相同,以幫助應用程序時,目標隊列是本地的,當目標隊列是遠程的。

在Service Broker中處理錯誤的方法是通過檢查自己的隊列中的響應。如果目標服務主動拒絕您的消息(即拒絕訪問,或XML格式錯誤或違反服務合同),那麼它將以錯誤結束對話,並且您會在自己的隊列中收到錯誤消息。如果你的信息無法傳送,那麼它將一直保留在傳送隊列中直到它到期,然後對話以錯誤結束,並且錯誤信息將再次放入你自己的隊列中。在使用BEGIN CONVERSATION指定的生命週期過期後,郵件超時。

因此,在您的情況下,當您禁用代理時,消息仍然被接受,但未傳遞。它被放置在傳輸隊列中。只要您啓用數據庫中的代理程序,該消息就會被提取併發送。當交付的可靠性成爲主要關注點時,這種行爲使得應用程序的編寫更爲簡單。即使目的地不可用(例如,用於服務維護),應用程序只是發送消息到達那裏,即使消息要傳遞需要數小時,數天甚至數週。對於與交付時間有關的應用程序,他們應該指定會話生存期。系統將嘗試在此生命中傳遞信息或放棄。如果放棄,則通過排隊錯誤消息(會話超時錯誤)通知發件人。

而且應用程序不應該爲響應等待。他們應該SEND,COMMIT並繼續,是事件驅動。當目標發回響應時,或者當底層基礎結構通知錯誤時,應用程序會在自己的隊列中獲取消息,並且應該對該消息作出反應

+0

你好Remus。在發送失敗的情況下,例如嘗試發送格式不正確的XML時,傳輸狀態爲'Service Broker收到此對話的錯誤消息。 Service Broker不會傳輸該消息;它將一直持續到應用程序結束對話「。有沒有辦法在隊列中識別這些消息?我的自動發件人隊列正在處理它們作爲正常郵件.. – milez

+0

@milez請問一個單獨的問題 –

+0

http://stackoverflow.com/q/38436673/5110359 :) – milez

相關問題