2011-11-01 43 views
5

我想:从表中的SQL选择行和更新相同的行

    从处理的表格,其中标志= 0
  1. 利用这些值都在第二表中的一些工作
  2. 选择N行N行
  3. 更新这些N行,并设置标志= 1

我有并行处理这样做同样的工作在一起,我想,以确保所有得到的唯一行的工作。我如何确保?

回答

5

我假设你在SQL Server上运行(由于标签),如果不是,那么我的答案是不适用的。 单独锁定是不够的。如果使用数据库记录锁定,SqL服务器将阻止其他进程尝试访问锁定的行,实际上,您一次只能处理一行。 您的解决方案是将行锁定与READPAST提示组合在一起,以便其他人锁定的行将被跳过。以下是各过程中应做到:

  1. 选择下一个解锁的行进行处理,并锁定
  2. 做的工作
  3. 更新该行并结束交易

select top 1 id, ... from TheTable with (updlock, readpast) where flag = 0

//do the work now

update TheTable set flag = 1 where id=<previously retrieved id>

这里的好处是,选择下一个解锁行并锁定它的操作是原子操作,因此它保证没有其他人能够选择相同的行。

+0

READPAST提示是否有用,一篇好文章http://www.mssqltips.com/sqlservertip/1257/processing-data-queues-in-sql-server-with-readpast-and-updlock/ – newbie

+0

随着SQL 2008 ,您可以在查询中使用OUTPUT子句和READPAST HINT将队列操作组合到一个语句中.http://www.sqlservercentral.com/articles/Queue+processing/69653/ – newbie

+0

@newbie是的,您可以使用输出来锁定和检索消息并将其标记为在单个查询中处理。但我一直在比较单个消息处理的性能,并且与两个查询相比没有收获(先选择然后更新)。实际上,使用OUTPUT查询时,多线程吞吐量稍低一些。也许在批处理中,Output子句会更快,但是对于单个消息来说不是这样。 – nightwatch

0

一种方法是让主程序向子线程分发段。

另一种方法是锁定表格,获得CEIL(N/#processes)行,其中flag = 0,将标志更新为2,然后释放锁定。然后下一个进程将会继续执行,因为flag = 2,它不会得到这些行。

你有两种方法来锁定表 - 你可以锁定整个事情,或者做一个限制的SELECT ... FOR UPDATE(不要得到太多的行)。参见:SELECT FOR UPDATE with SQL Server

甚至比设置标志为2更好的标志设置为process_id。然后,您只需更新所有行以分配数字,然后让流程开始工作,每个流程只检查自己的行。

相关问题