4

有一个小型系统,其中一个数据库表作为 MSSQL 2005 上的队列。几个应用程序正在写入该表,一个应用程序正在以 FIFO 方式读取和处理。

我必须让它更高级一点,才能创建一个分布式系统,在其中可以运行多个处理应用程序。结果应该是2-10个处理应用程序应该能够运行并且它们在工作期间不应相互干扰。

我的想法是用一行显示一个进程已经在处理它来扩展队列表。处理应用程序将首先使用它的标识符更新表,然后请求更新的记录。

所以是这样的:

start transaction
update top(10) queue set processing = 'myid' where processing is null
select * from processing where processing = 'myid'
end transaction

处理后,它将表的处理列设置为其他内容,例如“完成”或其他内容。

我对这种方法有三个问题。

第一:这可以以这种形式工作吗?

第二:如果有效,是否有效?您还有其他想法来创建这样的发行版吗?

第三:在 MSSQL 中,锁定是基于行的,但是在锁定一定数量的行之后,锁定会扩展到整个表。所以第二个应用程序不能访问它,直到第一个应用程序不释放事务。为了不锁定整个表,只创建行锁,选择(top x)可以有多大?

4

4 回答 4

6

这会起作用,但您可能会发现在多个进程尝试读取/更新相同数据的情况下,您会遇到阻塞或死锁。我为我们的一个系统编写了一个程序来做到这一点,它使用一些有趣的锁定语义来确保这种类型的东西在没有阻塞或死锁的情况下运行,描述在这里

于 2008-10-30T09:05:27.897 回答
1

这种方法对我来说看起来很合理,并且与我过去使用的方法相似——成功。

此外,行/表只会在更新和选择操作发生时被锁定,所以我怀疑行与表问题是否真的是一个主要考虑因素。

除非您的应用程序的处理开销低到可以忽略不计,否则我会保持“最高”值较低 - 可能只有 1。当然这完全取决于您的应用程序的细节。

说了这么多,我不是 DBA,所以也会对任何更多专家的答案感兴趣

于 2008-10-30T08:54:14.910 回答
1

关于您关于锁定的问题。您可以使用锁定提示强制它仅锁定行

update mytable with (rowlock) set x=y where a=b
于 2008-10-30T09:46:02.387 回答
1

这种方法的最大问题是您增加了对表的“更新”次数。尝试仅使用一个进程(更新 + 删除)和其他进程在表中插入数据,您会发现大约有一百万条记录时,它开始崩溃。

我宁愿有一个数据库消费者,并使用消息队列将处理数据传递给其他消费者。

于 2009-02-25T04:15:57.887 回答