2011-01-14 27 views
6

我正在使用SQL Server 2008 R2作为排队机制。我将项目添加到表中,并且外部服务读取并处理这些项目。这很好,但缺少一件事 - 我需要一种机制,我可以尝试从表中选择一行,如果没有,就会阻塞,直到存在(最好是在特定的时间段内)。SQL Server,使用表作为队列

任何人都可以建议我如何做到这一点?

+0

问题在SO上被问过很多次;请搜索SO – 2011-01-14 00:02:58

+4

一般地区的良好链接。 http://rusanu.com/2010/03/26/using-tables-as-queues/编辑:不确定它会回答你关于阻塞的具体问题,直到项目被添加到队列中为止。另外我不确定我在SO上看到过这个具体问题。 – 2011-01-14 00:04:19

+2

你知道SQL Server有*实际*队列,对吗? http://msdn.microsoft.com/en-us/library/ms345108(v=sql.90).aspx – 2011-01-14 00:10:11

回答

2

我需要机制,由此我可以尝试 以从表中选择 单个行,并且如果没有一个,块直到 有(优选为特定 一段时间)。

您可以循环并检查新行每一秒:

while not exists (select * from QueueTable) 
    begin 
    wait for delay '00:01' 
    end 

免责声明:这不是我的代码会用在生产系统上,但它确实你的要求。

1

以前建议使用Service Broker的评论者可能有最佳答案。 Service Broker允许您在等待更多输入时实质上阻塞。

如果服务代理过量,您应该考虑针对您的问题的不同方法。你能提供你想要做的更多细节吗?

8

实现非共享阻塞出队的唯一方法是WAITFOR (RECEIVE)。这意味着Service Broker队列,所有额外开销。

如果您使用的是普通tables as queues,您将无法实现非轮询阻止。您必须通过询问出队操作来轮询队列,并且如果它不返回任何内容,请稍后再次尝试休眠。

恐怕我会在这里不同意Andomar的观点:尽管他的答案是一个普通的问题,“桌子上有没有排?当涉及到排队时,由于重叠入队/出队的繁忙性,检查像这样的行是负载下(几乎)保证的死锁。在使用表格作为队列时,必须始终坚持基本的入队/出队操作,不要尝试花哨的东西。

0

让我与大家分享在这方面我的经验,你可能会发现它有用。

我的团队首先使用MSMQ事务队列来提供我们的异步服务(无论是IIS托管还是WAS)。我们遇到的最大问题是重负载下的MS DTC问题,例如100+信息/秒负载;所需要的只是一个缓慢的数据库操作,导致超时异常,而MS DTC会让房子失灵(可能会导致事务丢失),虽然我们不是100%确定的根直到今天,我们怀疑集群环境中的MS DTC存在一些严重问题。

因此,我们开始研究不同的解决方案。 Windows Server的服务总线(Azure服务总线的内部版本)看起来很有希望,但它是非事务性的,因此不符合我们的要求。

由于我们的交易需求,我们最终决定采用自己的方法,由构建Azure服务总线的人向我们提出的方法。从本质上讲,我们遵循Azure工作者角色模型中的工作者角色,该角色将通过某个队列提供;一个轮询阻塞模型。老实说,对我们来说,这比我们用过的其他东西好得多。对于这种服务的伪代码:

hasMsg = true 

while(true) 

    if(!hasMsg) 
     sleep 

    msg = GetNextMessage 

    if(msg == null) 
     hasMsg = false 
    else 
     hasMsg = true 

    Process(msg); 

我们发现,CPU使用率显著降低这种方式(比传统的WCF服务更低)。

棘手的部分当然是处理交易。如果您希望从队列中读取多个服务实例,那么您需要在SQL中使用read-past/updlock,并让.NET服务以一种方式登录事务,应该服务失败。在这种情况下,除了常规队列之外,您还需要使用重试/毒化队列作为表。