我有两个并发进程,我有两个查询,例如:
select top 10 * into #tmp_member
from member
where status = 0
order by member_id
然后
update member
set process_status = 1
from member inner join #tmp_member m
on member.member_id=m.member_id
我希望每个进程选择不同的行,因此如果第一个进程已经选择了一行,则不要在第二个进程的结果列表中使用该行。
我是否必须玩锁? UPDLOCK,ROWLOCK,READPAST提示可能吗?或者有更简单的解决方案吗?
感谢任何帮助,
欢呼声,
B'/ P>
答案 0 :(得分:3)
你需要提示。
请在此处查看我的回答:SQL Server Process Queue Race Condition
但是,您可以使用OUTPUT clause将上述查询缩短为单个语句。否则你也需要一个事务(假设每个进程一个接一个地执行2个语句)
update m
set process_status = 1
OUTPUT Inserted.member_id
from
(
SELECT top 10
process_status, member_id
from member WITH (ROWLOCK, READPAST, UPDLOCK)
where status = 0
order by member_id
) m
摘要:如果您想要多个流程
select 10 rows where status = 0
set process_status = 1
...然后使用此代码。
答案 1 :(得分:0)
问题是您的选择/更新不是原子的 - 第二个进程可能会在选择的第一个进程和更新之前选择前10个项目。
可以在UPDATE语句中使用OUTPUT子句使其成为原子。有关详细信息,请参阅文档,但基本上您可以编写如下内容:
DECLARE @MyTableVar table(member_ID INT)
UPDATE TOP (10) Members
SET
member_id = member_id,
process_status = 1
WHERE status = 0
OUTPUT inserted.member_ID
INTO @MyTableVar;
之后@MyTableVar应该包含所有更新的成员ID。
答案 2 :(得分:0)
为了满足您在成员表上使用多个进程的目标,您不需要“玩锁定”。您需要将#tmp_member
表更改为全局临时表或永久表。该表还需要一列来跟踪管理成员行/
您将需要一种方法来为将要使用该表的每个进程提供某种ID。然后将修改第一个查询以排除其他进程在表中的任何条目。将修改第二个查询以仅包括此过程的那些条目