代码之家  ›  专栏  ›  技术社区  ›  Bryan Crosby

适用于此方案的可序列化事务?

  •  2
  • Bryan Crosby  · 技术社区  · 14 年前

    编辑:SQL Server 2005

    我有一个客户应用程序在5个独立的服务器上运行。每个应用程序都在查看一个调度表。我想确保没有任何一台机器可以同时访问同一个记录。每台服务器一次只能处理一行。基本上,应用程序只选择可以运行的下一个可用记录。如果未选择任何内容,它将不执行任何操作,并等待另一分钟,然后重试。

    [编辑:更具体地说,从未从dbo.the_表中删除过任何行。它简单地标记isprocessing=1,这样其他机器就不会接收到它了]

    我的存储过程(SQL Server)如下所示:

    SET TRANSACTION ISOLATION LEVEL SERIALIZABLE
    BEGIN TRAN
    
    SET @ScheduleId = SELECT TOP 1 ScheduleId FROM dbo.the_table WHERE NextRun <= GETDATE() AND IsEnabled = 1
    
    UPDATE dbo.the_table SET IsProcessing=1 WHERE ScheduleId = @ScheduleId
    
    --Edit: Return this to the program so we can do stuff with the data
    SELECT * FROM dbo.the_table WHERE ScheduleId = @ScheduleId
    
    IF @@ERROR = 0
    COMMIT TRAN
    ELSE
    ROLLBACK TRAN
    

    我想确定当事务正在进行时,其他机器的任何select语句都将被阻塞,直到阻塞事务提交事务为止。(例如,机器A启动一个事务——如果B、C、D或E尝试并选择,它们将等待事务提交)。

    1 回复  |  直到 14 年前
        1
  •  4
  •   Martin Smith    14 年前

    您使用的是什么版本的SQL Server?如果sql2005+可以在一个语句中完成这一切

    ;WITH s AS
    (
    SELECT TOP 1 * 
    FROM dbo.the_table WHERE NextRun <= GETDATE() AND IsEnabled = 1
    AND IsProcessing = 0 /*?*/
    --ORDER BY ScheduleId  ?
    )
    UPDATE    s  WITH (ROWLOCK, READPAST)
    SET     IsProcessing=1 
    OUTPUT INSERTED.*  /*Return row that was updated*/