重要なのは、受信しているキュー アイテムのロック (行またはテーブル) を取得することです。いくつかの方法を使用できますが、私のお気に入りは OUTPUT 句を使用した UPDATE です。どちらも、テーブルへのシリアル化されたアクセスを生成します。
例:
CREATE PROCEDURE spGetNextItem_output
BEGIN
BEGIN TRAN
UPDATE TOP(1) Messages
SET [Status] = 1
OUTPUT INSERTED.MessageID, INSERTED.Data
WHERE [Status] = 0
COMMIT TRAN
END
CREATE PROCEDURE spGetNextItem_tablockx
BEGIN
BEGIN TRAN
DECLARE @MessageID int, @data xml
SELECT TOP(1) @MessageID = MessageID, @Data = Data
FROM Messages WITH (ROWLOCK, XLOCK, READPAST) --lock the row, skip other locked rows
WHERE [Status] = 0
UPDATE Messages
SET [Status] = 1
WHERE MessageID = @MessageID
SELECT @MessageID AS MessageID, @Data as Data
COMMIT TRAN
END
テーブル定義:
CREATE TABLE [dbo].[Messages](
[MessageID] [int] IDENTITY(1,1) NOT NULL,
[Status] [int] NOT NULL,
[Data] [xml] NOT NULL,
CONSTRAINT [PK_Messages] PRIMARY KEY CLUSTERED
(
[MessageID] ASC
)
)