我的SQL Server 2008 DB中有一个简单的表:
Tasks_Table
-id
-task_complete
-task_active
-column_1
-..
-column_N
该表存储了必须由服务执行的未完成任务的指令。
我希望将来可以扩展我的系统。到目前为止,只有1台计算机上的1项服务从表中读取。我有一个存储过程,它选择所有未完成和非活动的任务。当服务开始处理任务时,它会更新所有返回行中的task_active标志。
要启用系统扩展,我想在更多计算机上启用服务部署。因为我想阻止任务返回到多个服务,所以我必须更新返回未完成和非活动任务的存储过程。
我认为我必须锁定表格(一次只有1个阅读器 - 我知道我必须使用适当的ISOLATION LEVEL),并在返回结果集之前更新结果集的每一行中的task_active标志。
所以我的问题是如何在返回之前修改存储过程中的SELECT结果集?
答案 0 :(得分:2)
这是典型的出队模式,使用OUTPUT子句实现,并且在MSDN中有描述,请参阅OUTPUT Clause (Transact-SQL)中的队列段落:
UPDATE TOP(1) Tasks_Table WITH (ROWLOCK, READPAST)
SET task_active = 1
OUTPUT INSERTED.id,INSERTED.column_1, ...,INSERTED.column_N
WHERE task_active = 0;
ROWLOCK,READPAST提示允许高吞吐量和高可靠性:多线程/已处理可以在多线程/进程出列任务时排队新任务。没有订单保证。
<强>更新强>
如果您想订购结果,可以使用CTE:
WITH cte AS (
SELECT TOP(1) id, task_active, column_1, ..., column_N
FROM Task_Table WITH (ROWLOCK, READPAST)
WHERE task_active = 0
ORDER BY <order by criteria>)
UPDATE cte
SET task_active = 1
OUTPUT INSERTED.id, INSERTED.column_1, ..., INSERTED.column_N;
我在文章Using Tables as Queues上讨论了这个和其他入队/出队技术。