0

我想创建一个以 sql 数据库作为后端的简单队列。该表具有字段、id、taskname、runat(datetime) 和 hidden(datetime)。

我想确保队列项目不会运行一次且仅运行一次。

这个想法是当客户端想要出列时,存储过程选择第一项(按 runat 和 hidden < now 排序),将隐藏字段设置为当前时间 + 2 分钟并返回该项目。

MS Sql(准确地说是Azure)wokr,两个客户端如何能够同时运行并且都将相同的项目设置为隐藏并返回它?或者我可以确定它们一个一个地运行,而第二个不会返回与第一个更改隐藏字段相同的项目?

4

2 回答 2

3

关键是在您接收的队列项目上获得锁定(行或表)。您可以使用几种方法,我最喜欢的是 UPDATE with OUTPUT 子句。两者都将产生对表的序列化访问。

例子:

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
    )
) 
于 2012-10-06T21:46:04.560 回答
0

Windows Azure SQL 数据库在并发方面的行为就像 SQL Server 数据库一样。这是一个数据库问题,而不是 Windows Azure 问题。

现在:如果您使用 Windows Azure 队列(或服务总线队列)而不是实现自己的,那么该行为有据可查。例如:使用 Azure 队列,先入者获取队列项目,然后将该项目标记为不可见,直到它被删除或达到超时期限。

于 2012-10-06T18:33:15.580 回答