我们假设我有一个存储任务的表格,这些表格可能具有类似的状态,即“处理”和“处理”状态。并且“完成了”。由于我有多个客户负责处理这些任务,我想确保只有一个客户抓住某个任务来处理它。
为了避免过多的数据库请求,客户端会在一个请求中处理多个(10,100,...)任务。
在SQL Server中实现此目的的最佳方法是什么?
我能否以某种方式选择要完成的任务并同时更新它们以将其标记为“处理”?
答案 0 :(得分:0)
假设您存储任务的表与此类似:
CREATE TABLE [TASKQUEUE]
(
[TASKID] INT ,
[CLIENTID] INT ,
[STATE] TINYINT ,
[DESCRIPTION] VARCHAR(100)
)
GO
TASKID是主键, CLIENTID将标记为特定客户端处理的行, STATE将包含您可能的一种状态('待办','处理','完成')。
然后,您抓取任务的存储过程可以是:
CREATE PROCEDURE [GETTASK]
@MAX INT = 100 ,
@CLIENTID INT ,
@STATE TINYINT
-- @STATE:
-- 1: to do
-- 2: processing
-- 3: done
AS
BEGIN
UPDATE [TASKQUEUE]
SET [CLIENTID] = @CLIENTID ,
[STATE] = 2
WHERE [TASKID] IN (
SELECT TOP(@MAX) [TASKID]
FROM [TASKQUEUE]
WHERE [STATE] = 1 AND [CLIENTID] IS NULL);
SELECT [TASKID] , [DESCRIPTION]
FROM [TASKQUEUE]
WHERE [CLIENTID] = @CLIENTID AND [STATE] = 2;
END;
如果您使用READ COMMITTED隔离级别(默认)或更高级别 - UPDATE将负责多个同时请求的同步。没有两个请求可以同时更新相同的TASKQUEUE行。
如果第二个请求尝试在第一个请求的更新后立即调用UPDATE - 行已经被修改,并且WHERE [STATE] = 1 AND [CLIENTID] IS NULL
子句将不会检索。