我们有一个从sql server读取数据的.Net服务。做一些处理然后再次更新sql server表。现在我们需要运行此服务的多个实例。所以我遇到了以下问题。
在我看来,我需要创建一个列来指定是否读取行。 你能推荐一些像MSMQ或Service Broker
的东西吗?答案 0 :(得分:0)
通过多个服务实例轮询数据库是您需要处理以下几个问题的选项:
您可以使用带有OUTPUT子句的UPDATE语句来使用这样的代码进行原子更新/选择:
DECLARE @fetched TABLE (id INT)
UPDATE D
SET D.Processed=1,D.ProcessId=123,D.StartTime=GETDATE()
OUTPUT inserted.id INTO @fetched
FROM queueData D
INNER JOIN (
SELECT TOP 10 T10.id
FROM queueData T10
WHERE T10.Processed=0
ORDER BY id
) Top10 ON D.id=Top10.id
SELECT * FROM @fetched
您可以直接使用MSMQ或Azure Service Bus,也可以通过MassTransit API为您提取队列系统的详细信息。
还有另一种选择,那就是使用SQL Server Service Broker。这种方法的优点是你不需要在MSMQ或其他一些队列系统上引入额外的依赖,你只需要在SQL服务器中启用Service Broker然后使用TSQL将消息放入队列并从队列中获取消息。此外,SQL Server将处理事务。
-- enable the Service Broker
ALTER DATABASE test SET ENABLE_BROKER
GO
-- Message Type
CREATE MESSAGE TYPE TestMessage VALIDATION = NONE
GO
-- Contract
CREATE CONTRACT TestContract (TestMessage SENT BY INITIATOR)
GO
-- Send Queue
CREATE QUEUE TestSendQueue
GO
-- Receive Queue
CREATE QUEUE TestReceiveQueue
-- Create Send Service
CREATE SERVICE TestSendService ON QUEUE TestSendQueue (TestContract)
GO
-- Create Receive Service
CREATE SERVICE TestReceiveService ON QUEUE TestReceiveQueue (TestContract)
GO
-- Dialog using on contract
DECLARE @testDialog uniqueidentifier
DECLARE @Message VARCHAR(128)
BEGIN DIALOG CONVERSATION @testDialog
FROM SERVICE TestSendService
TO SERVICE 'TestReceiveService'
ON CONTRACT TestContract
WITH ENCRYPTION = OFF
-- Send messages
SET @Message = 'Very First Message';
SEND ON CONVERSATION @TestDialog MESSAGE TYPE TestMessage (@Message)
GO
-- Receive messages from Receive Queue
RECEIVE TOP(1) CONVERT(VARCHAR(MAX), message_body) AS Message
FROM TestReceiveQueue
GO
上述代码部分来自http://blog.sqlauthority.com/2009/09/21/sql-server-intorduction-to-service-broker-and-sample-script/。
答案 1 :(得分:0)
您可以考虑创建一个表,类似于ReservedRows来跟踪正在处理的行,它包含目标表中行的ID。
然后在服务中,首先锁定ReservedRows表,然后读取您要处理的数据,排除已经在ReservedRows中的数据,将您正在读取的记录的ID插入ReservedRows,然后打开桌子。由于您插入了正在处理的行的ID,因此在完成之前,其他服务实例将不会处理这些行。
完成处理行并更新目标表后。从ReservedRows表中删除刚刚处理的行的ID,以便其他实例可以在以后处理这些ID。