2

编辑:SQL Server 2005

我有一个客户应用程序在 5 个单独的服务器上运行。每个应用程序都在查看一个调度表。我想确保没有机器可以像任何其他机器一样同时访问相同的记录。每个服务器一次只能处理 1 行。基本上,应用程序只选择可以运行的下一条可用记录。如果没有选择任何内容,它就什么也不做,然后再等待一分钟,然后再试一次。

[编辑:更具体地说,不会从 dbo.the_table 中删除任何行。它只是标记 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 尝试并选择,它们将等到事务提交)。

4

1 回答 1

4

您使用的是哪个版本的 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*/
于 2010-08-04T00:09:56.283 回答