TABLOCKX против СЕРИАЛИЗИРУЕМЫХ - PullRequest
4 голосов
/ 07 февраля 2011

У меня есть серия запросов T-SQL, которые мне нужно выполнить атомарно. (См. Ниже) ... Цель состоит в том, чтобы позволить одному пользователю одновременно извлекать одну уникальную строку и запретить другим пользователям одновременно получать одну и ту же строку.

До сих пор я видел два возможных решения. 1) Табличные подсказки (HOLDLOCK, TABLOCKX) и 2) Уровень изоляции транзакции (SERIALIZABLE) ...

Мои вопросы:

  1. Какой вариант лучше?

  2. Есть ли другое / лучшее решение?

DECLARE @recordId int;

SELECT @recordId = MIN([id])
FROM Exceptions
WHERE [status] = 'READY';

UPDATE Exceptions
SET [status] = 'PROCESSING',
    [username] = @Username
WHERE [id] = @recordId;

SELECT *
FROM Exceptions
WHERE [id] = @recordId;

Ответы [ 2 ]

7 голосов
/ 07 февраля 2011

В этом случае

  • HOLDLOCK = SERIALIZABLE = длительность, параллелизм
  • TABLOCKX = эксклюзивная блокировка стола

Эти два понятия различны, и ни то, ни другое не соответствует вашему желанию.

Чтобы сделать то, что вы хотите, чтобы избежать условий гонки , вам необходимо принудительно установить неблокирующую (READPAST) монопольную (UPDLOCK) блокировку уровня строки (ROWLOCK). Вы также можете использовать предложение OUTPUT, чтобы сделать его единым оператором, который будет атомарным. Это хорошо масштабируется.

UPDATE
    E
SET
   [status] = 'PROCESSING', [username] = @Username
OUTPUT
   INSERTED.*
FROM
   (
    SELECT TOP 1 id, [status], [username]
    FROM Exceptions (ROWLOCK, READPAST, UPDLOCK)
    WHERE [status] = 'READY'
    ORDER BY id
   ) E

В общем, замки имеют 3 аспекта

  • Гранулярность = что заблокировано = строка, страница, таблица (PAGLOCK, ROWLOCK, TABLOCK)
  • Уровень изоляции = длительность блокировки, параллелизм (HOLDLOCK, READCOMMITTED, REPEATABLEREAD, SERIALIZABLE)
  • Режим = совместное использование / эксклюзивность (UPDLOCK, XLOCK)

И

  • "комбинированный", например NOLOCK, TABLOCKX
2 голосов
/ 07 февраля 2011

Вы описываете типичную обработку очереди, и не требуются ни tablockx, ни serializable, и они на самом деле не будут работать. Я рекомендую вам перейти на Использование таблиц в качестве очередей для углубленного обсуждения того, что возможно, а что нет. Суть этого:

  • выберите правильный кластерный ключ (критический!)
  • Использовать предложение OUTPUT
  • Использовать READPAST
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...