В SQL 2008+ следующая таблица очередей и операции постановки в очередь предназначены для обеспечения эффективной очереди заданий в потоках между несколькими генераторами и потребителями в произвольных именованных очередях в необязательной частично упорядоченной последовательности.Тривиальная поддержка обработки вредоносных сообщений с помощью RetryLater (), FailNow (), Reset () (не показана).
CREATE TABLE [dbo].[Queue](
[ID] BIGINT IDENTITY(1,1) NOT NULL CONSTRAINT [PK_Queue] PRIMARY KEY,
[PredecessorID] BIGINT NULL,
[QueueName] NVARCHAR(255) NOT NULL,
[DataType] NVARCHAR(255) NOT NULL,
[Data] NVARCHAR(MAX) NOT NULL,
[RetriesRemaining] INT CONSTRAINT [CHK_RetryCount] CHECK ([RetriesRemaining] IS NULL OR 0 <= [RetriesRemaining]),
[IsFailed] AS (CASE WHEN [RetriesRemaining] IS NULL OR 0 < [RetriesRemaining] THEN 0 ELSE 1 END) PERSISTED,
[QueuedOnUTC] DATETIME NOT NULL DEFAULT (GETUTCDATE()),
[DelayUntilUTC] DATETIME NULL,
[LastFailedOnUTC] DATETIME NULL,
[LastFailure] NVARCHAR(MAX)
)
-- Enqueue
INSERT INTO [dbo].[Queue]
(
[PredecessorID],
[QueueName],
[DataType],
[Data],
[RetriesRemaining]
)
VALUES
(
@PredecessorID,
@QueueName,
@DataType,
@Data,
@RetriesRemaining
)
-- Dequeue
SELECT
[Dequeued].[ID],
[Dequeued].[QueueName],
[Dequeued].[DataType],
[Dequeued].[Data]
FROM
[dbo].[Queue] AS [Dequeued] WITH (ROWLOCK, UPDLOCK, READPAST)
LEFT JOIN
[dbo].[Queue] AS [Predecessor] ON
[Dequeued].[PredecessorID] = [Predecessor].[ID]
WHERE
[Dequeued].[IsFailed] = 0
AND [Dequeued].[QueueName] = @QueueName
AND ([Dequeued].[DelayUntilUTC] IS NULL OR [Dequeued].[DelayUntilUTC] < GETUTCDATE())
AND [Predecessor].[ID] IS NULL
Потребительские транзакции остаются открытыми с до Dequeue () через обработку на стороне приложения и до DELETE, RetryLater () или FailNow ().
- Является ли этот дизайн звуком?
- Эта установка свободна от блокировки?
- Что отрицательно Может ли IDX_Queue_IsFailed_QueueName_DelayUntilUTC или другие индексы повлиять на взаимную блокировку?
- Какие другие индексы полезны?
- Как разделение таблиц (queueName) или другие функции могут улучшить масштабируемость?
В соответствии с задумкой, Генераторы сигнализируют Потребителям через внешний механизм, что данные были помещены в очередь, чтобы избежать жесткого опроса.Вместо этого (и без SQL ServiceBroker) есть способ использовать блокировки SQL для эффективной блокировки получателя, для которого нет доступных строк, пока генератор не записал в именованную очередь?
CREATE INDEX [IDX_Queue_IsFailed_QueueName_DelayUntilUTC] ON[dbo]. [Queue] ([IsFailed], [QueueName], [DelayUntilUTC])
Кроме того, я предполагаю, что OrderBy не имеет значения, если мы всегда получаем одинбез предшественника.