在Select上锁定SQL

时间:2013-10-16 22:56:43

标签: sql

我有一个用作队列的SQL表。

基本上,我有一个多线程进程,它读取未处理的项目并对这些项目进行相应的操作,并设置处理的位。假设两个进程非常接近,[进程1]读取队列中的下一个项目。

如果出于某种原因[进程1]还没有时间设置已处理的位,如何阻止[进程2]读取刚刚读取的相同项目[进程1]? / p>

注意:还有另一个将项目添加到队列的整个过程。我不想限制/阻止该过程添加项目。

4 个答案:

答案 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

这里的关键是首先进行更新,然后返回在此事务中更新的行。