SSB 是 SQL Server 內建的**異步消息隊列框架**,支援可靠傳輸、事務一致性、跨實例路由。適用於:異步業務解耦、跨庫/跨服務器數據同步、長時間任務排隊、事件驅動架構。
USE master; GO
CREATE DATABASE Inventory; GO
USE Inventory; GO
CREATE TABLE InventoryTbl (TitleId NVARCHAR(6) NOT NULL, Quantity INT NOT NULL, PRIMARY KEY(TitleId,Quantity));
INSERT InventoryTbl VALUES ('PC1001',100),('PC1002',200),('PC1003',300),('PC1004',400);
-- 消息類型
CREATE MESSAGE TYPE [//mark/v10/types/inventory] VALIDATION = WELL_FORMED_XML;
CREATE MESSAGE TYPE [//mark/v10/types/inventoryresponse] VALIDATION = WELL_FORMED_XML;
-- 合約:發起方發 inventory,目標方回 inventoryresponse
CREATE CONTRACT [//mark/v10/contracts/inventorycontract]
([//mark/v10/types/inventory] SENT BY INITIATOR,
[//mark/v10/types/inventoryresponse] SENT BY TARGET);
-- 隊列與服務
CREATE QUEUE [InventoryClientQueue];
CREATE SERVICE [//mark/v10/services/inventoryclient] ON QUEUE [InventoryClientQueue];
CREATE QUEUE [InventoryQueue];
CREATE SERVICE [//mark/v10/services/inventory] ON QUEUE [InventoryQueue]
([//mark/v10/contracts/inventorycontract]);
BEGIN TRAN;
DECLARE @dialog UNIQUEIDENTIFIER;
BEGIN DIALOG CONVERSATION @dialog
FROM SERVICE [//mark/v10/services/inventoryclient]
TO SERVICE '//mark/v10/services/inventory'
ON CONTRACT [//mark/v10/contracts/inventorycontract]
WITH ENCRYPTION = OFF;
SEND ON CONVERSATION @dialog MESSAGE TYPE [//mark/v10/types/inventory]
(
N'
PC1001
102
'
);
COMMIT TRAN;
BEGIN TRAN;
DECLARE @dialog UNIQUEIDENTIFIER, @msg XML, @qty INT, @title NVARCHAR(128);
RECEIVE TOP(1)
@dialog = conversation_handle,
@msg = message_body
FROM [dbo].[InventoryQueue];
IF @dialog IS NOT NULL
BEGIN
SET @qty = @msg.value('(/InventoryUpdate/Quantity)[1]','INT');
SET @title = @msg.value('(/InventoryUpdate/TitleId)[1]','NVARCHAR(100)');
UPDATE InventoryTbl SET Quantity = @qty WHERE TitleId = @title;
END CONVERSATION @dialog;
END
COMMIT TRAN;
-- 1. 創建處理存儲過程
CREATE PROC InventoryProc AS
BEGIN
SET NOCOUNT ON;
DECLARE @dialog UNIQUEIDENTIFIER, @msg XML, @qty INT, @title NVARCHAR(128);
WAITFOR (
RECEIVE TOP(1)
@dialog = conversation_handle,
@msg = message_body
FROM [dbo].[InventoryQueue]
), TIMEOUT 5000; -- 5 秒無消息則退出
IF @dialog IS NOT NULL
BEGIN
SET @qty = @msg.value('(/InventoryUpdate/Quantity)[1]','INT');
SET @title = @msg.value('(/InventoryUpdate/TitleId)[1]','NVARCHAR(100)');
UPDATE InventoryTbl SET Quantity = @qty WHERE TitleId = @title;
END CONVERSATION @dialog;
END
END;
GO
-- 2. 啟用隊列激活
ALTER QUEUE [InventoryQueue]
WITH ACTIVATION (
STATUS = ON,
PROCEDURE_NAME = InventoryProc,
MAX_QUEUE_READERS = 2, -- 並發消費者數
EXECUTE AS SELF
);
GO
自此,**只要有消息進隊列,SQL Server 自動並發啟動 InventoryProc 處理**,無需外部輪詢服務。
SELECT * FROM [InventoryQueue];SELECT message_type_name FROM [InventoryClientQueue];sys.conversation_endpoints、sys.transmission_queue 監控會話狀態、傳輸隊列。| 項目 | 建議 |
|---|---|
| 加密 | 跨實例必開 WITH ENCRYPTION = ON,需憑證/主鑰體系 |
| 持久化 | 隊列本質是表,受數據庫備份/恢復保護,消息不丟失 |
| 錯誤處理 | 存儲過程內 TRY...CATCH,失敗可 ROLLBACK 讓消息回隊列重試 |
| 有序性 | 同一會話保證順序;不同會話並行,業務需自行設計分區鍵 |
| 清理策略 | 定期 END CONVERSATION 清理已結束會話,防止 sys.conversation_endpoints 膨脹 |
SSB 將「消息中間件」內建進數據庫引擎,以事務為邊界實現**業務與消息原子性**,省去 Kafka/RabbitMQ 運維成本。掌握「類型→合約→隊列→服務→會話→激活」六步走,即可在 SQL Server 內構建企業級異步架構。