编辑: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 尝试并选择,它们将等待事务提交)。
最佳答案
您使用的是哪个版本的 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*/
关于sql-server - 可序列化事务适合这种场景吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3401641/