【发布时间】:2011-11-01 22:59:33
【问题描述】:
我想:
- 从表中选择 N 行进行处理,其中 flag=0
- 使用这 N 行中的值在第二个表上做一些工作
- 更新这 N 行并设置 flag=1
我有并行的进程一起做同样的工作,我想确保所有的人都能在唯一的行上工作。我如何确保这一点?
【问题讨论】:
标签: sql sql-server database sql-server-2005 sql-server-2008
我想:
我有并行的进程一起做同样的工作,我想确保所有的人都能在唯一的行上工作。我如何确保这一点?
【问题讨论】:
标签: sql sql-server database sql-server-2005 sql-server-2008
我假设您在 SQL Server 上运行(因为标签),如果不是,那么我的答案不适用。 单独锁定是不够的。如果您使用数据库记录锁定 Sql 服务器将阻止尝试访问锁定行的其他进程,实际上您一次只能处理一行。 您的解决方案是将行锁定与 READPAST 提示结合起来,以便跳过其他人锁定的行。以下是每个进程应该执行的操作:
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>
这里的好处是选择下一个未锁定行并锁定它的操作是原子的,因此它保证没有其他人能够选择同一行。
【讨论】:
一种方法是让主程序将段分发给子线程。
另一种方法是锁表,获取CEIL(N/#processes) rows where flag = 0,将flag更新为2,然后释放锁。然后下一个进程将继续,因为它得到了锁,并且由于 flag = 2 它不会得到那些行。
您有两种锁定表的方法 - 您可以锁定整个表,或者执行 SELECT ... FOR UPDATE 限制(不获取太多行)。见:SELECT FOR UPDATE with SQL Server
将标志设置为 process_id 比将标志设置为 2 更好。然后你所要做的就是更新所有的行来分配数字,然后让这个过程开始工作,每个人只检查自己的行。
【讨论】: