Как предотвратить / устранить тупики в MSSQL?
Мой Windows-сервис, написанный на C#, иногда (несколько раз в неделю) регистрирует сообщение примерно так:
getClientData: Транзакция (идентификатор процесса ###) была заблокирована для ресурсов блокировки с другим процессом и была выбрана в качестве жертвы тупика. Перезапустите транзакцию.
getClientData
моя собственная функция C#, которая просто вызывает хранимую процедуру. Хранимая процедура является реализацией очереди приоритет + ожидание в mssql. Я получил идею отсюда.
Я только что нашел это объяснение того, как тупик может произойти без транзакций в простом запросе выбора (+ дополнительные вещи, происходящие в фоновом режиме). Теперь эти взаимоблокировки не так уж и важны, потому что это не приводит к сбою моего сервиса (я просто повторяю запросы), но я хотел бы знать, возможно ли избавиться от этих взаимоблокировок.
Ох, и данные вставляются в [dbo].[tbl_client_data]
таблица по одной строке за раз из нескольких разных источников (все они просто простые вставки по одной строке, хотя).
Хранимая процедура выглядит примерно так (столбцов данных больше, но мне это не важно):
CREATE PROCEDURE [dbo].[sp_get_client_data]
@client_id [int],
@limit [int] = 0
AS
BEGIN
IF(@limit < 0) SET @limit = 0;
DECLARE @data TABLE
(
[id] [int],
[data] [varchar](max),
[client_id] [int],
[ts] [datetime],
[priority] [tinyint]
);
IF(@limit > 0)
BEGIN
DELETE TOP(@limit)
FROM [dbo].[tbl_client_data]
OUTPUT DELETED.[id]
,DELETED.[data]
,DELETED.[client_id]
,DELETED.[ts]
,DELETED.[priority]
INTO @data
WHERE [id] IN (SELECT TOP(@limit) [id]
FROM [dbo].[tbl_client_data] with(nolock)
WHERE ([ts] IS NULL OR [ts] <= GETDATE())
AND [client_id] = @client_id
ORDER BY [priority], [ts]);
END
SELECT *
FROM @data
ORDER BY [priority], [ts];
END
Итак, мой вопрос - есть ли способ избавиться от этих случайных (очень редких) тупиков или я должен просто игнорировать их и просто повторить запросы, как я знаю?