我有一个用作队列的SQL表。
基本上,我有一个多线程进程,它读取未处理的项目并对这些项目进行相应的操作,并设置处理的位。假设两个进程非常接近,[进程1]读取队列中的下一个项目。
如果出于某种原因[进程1]还没有时间设置已处理的位,如何阻止[进程2]读取刚刚读取的相同项目[进程1]? / p>
注意:还有另一个将项目添加到队列的整个过程。我不想限制/阻止该过程添加项目。
答案 0 :(得分:1)
想出来:
BEGIN TRAN
SELECT TOP * FROM TABLE WITH (XLOCK, ROWLOCK, READPAST)
UPDATE TABLE SET Processed = 1
END TRAN
XLOCK 和 ROWLOCK 锁定我刚刚读取的行。 READPAST 将读取当前锁定的行。
因此,[进程1]读取顶行并锁定它。 [进程2]将自动读取下一个未锁定(未读)行。
答案 1 :(得分:0)
您有几个选择。如何在表格中加入status
列?例如,将此值设置为1
意味着正在处理记录。当您查询要处理的记录时,只需忽略状态为1的任何记录。
答案 2 :(得分:0)
你说有一个 Processed 位。您可以在每次读取新项目时进行比较,以确保其已处理位未设置为1.
如果 Process1 需要很长时间才能运行,那么: 1.在 Process1 的开头将已处理位设置为1或 2.如Ash所述创建一个新位,并将该位设置为1。
答案 3 :(得分:0)
向talble添加一个新列,让我们称之为processedId
创建一个执行以下操作的存储过程:
生成一个guid。 将processedId设置为等于被处理的id为null的guid值。 返回表格中所有的行,其中processedid等于你生成的guid。
declare @processedId uniqueidentifier = NEWID()
update table set processedid=@procesedId where processedid is null
select * from table where processedid = @processedid
这里的关键是首先进行更新,然后返回在此事务中更新的行。