假设我有一个SQL Server数据库表,其中包含X(> 1,000,000)条记录,需要通过某些工作进程(控制台)逐个处理(获取数据,执行外部操作,更新db状态)应用程序,Windows服务,Azure工作者角色等).我需要保证每行只处理一次.无论有多少机器/流程用于处理消息,理想的排他性都将得到保证.我最担心的是两个SELECT同时抓取相同的行.
我知道有更好的数据存储在那里排队,但我没有这个项目的奢侈品.我有完成这个想法,但我正在寻找更多.
我遇到过这种情况.
InProcess
向表中添加一列,默认值为0.在使用者流程中:
UPDATE tbl SET Inprocess = @myMachineID WHERE rowID = (SELECT MIN(rowID) WHERE InProcess = 0)
现在该机器拥有该行,您可以毫无顾虑地查询其数据.通常你的下一行将是这样的:
SELECT * FROM tbl WHERE rowID = (SELECT MAX(rowID) FROM tbl WHERE ProcessID = @myMachineID)
您还必须在Done
该行中添加某种类型的标志,以便您可以判断该行是否已声明但处理是否不完整.
编辑
在UPDATE
得到一个排它锁(请参阅MSDN).我不确定SELECT
子查询中是否允许从中分割出来UPDATE
; 如果是这样,你必须把它们放在交易中.
@Will A发布一个链接,建议用这个开始你的批次将保证:
SET TRANSACTION ISOLATION LEVEL READ COMMITTED
......但我还没试过.
@Martin Smith的链接也有一些好处,看看这个OUTPUT
子句(在SQL 2005中添加).
最后一次编辑
在评论中非常有趣的交流,我在这里肯定学到了一些东西.这就是SO的用途,对吧?
仅仅为了颜色:当我在2004年使用这种方法时,我有一堆网络抓取工具将URL-to-search转储到一个表中,然后从同一个表中拉出他们的下一个URL-to-crawl.由于爬虫试图吸引恶意软件,他们随时都可能崩溃.