Получить обновление таблицы блокировки при запуске хранимой процедуры в SQL Server - PullRequest
2 голосов
/ 04 июня 2010

Я пишу хранимую процедуру SQL Server, в которой я хочу заблокировать таблицу для обновления перед выполнением тела хранимой процедуры. Я не хочу запретить другим процессам читать таблицу, но я хочу, чтобы другие процессы обновляли таблицу.

Вот моя первая попытка:

CREATE PROCEDURE someProcedure
BEGIN
   SET TRANSACTION ISOLATION LEVEL READ COMITTED
   BEGIN TRANSANCTION
     SELECT COUNT(*) FROM TheTable WITH (UPDLOCK, TABLOCK)

     -- Pause procedure so that we can view the locks with sp_lock
     WAITFOR DELAY '00:15'

     -- Do stuff
   COMMIT
END

Когда я выполняю хранимую процедуру и вызываю sp_lock, я вижу, что таблица действительно заблокирована. Однако он блокируется с помощью эксклюзивной блокировки вместо блокировки обновления:

spid | dbid | ObjId     | IndId | Type | Resource | Mode | Status
------------------------------------------------------------------
63   | 10   | 233208031 | 0     | TAB  |          | X    | GRANT

Как вместо этого получить блокировку обновления (U)?

Ответы [ 2 ]

5 голосов
/ 06 июня 2010

Вы сказали:

Я не хочу мешать другим процессы от чтения таблицы, но Я хочу предотвратить другие процессы обновление таблицы.

Вам просто нужна общая блокировка чтения на время TXN. Это означает, что никакой другой процесс не может получить блокировку «записи» в сочетании с TABLOCK. И вам тоже не нужен COUNT.

...
   BEGIN TRANSANCTION
     SELECT TOP 1 KeyCol FROM TheTable WITH (TABLOCK, HOLDLOCK)
...

Почему вы думаете, что хотите ОБНОВИТЬ БЛОКИРОВКУ?

HOLDLOCK или SERIALIZABLE

Эквивалентно SERIALIZABLE. Для большего информация, см. SERIALIZABLE позже в Эта тема. HOLDLOCK применяется только к таблица или представление, для которого это указано и только на срок транзакция, определенная утверждение, что оно используется в. ... Делает общие блокировки более строгими удерживая их, пока транзакция завершено, вместо того, чтобы выпустить общая блокировка, как только требуется таблица или страница данных больше не необходимо, имеет ли транзакция было завершено или нет.

Редактировать после комментария:

  • «эксклюзивная блокировка» означает «только один процесс, использующий данные».
  • «SERIALIZABLE» в основном означает удерживать блокировки (общие, эксклюзивные, что угодно) намного дольше.

Нельзя указать "эксклюзивную блокировку" и , чтобы другие процессы могли читать. Концепции являются взаимоисключающими. Вы хотите предотвратить запись во всю таблицу, что будет делать persisted shared / read lock. Вот тут и начинается SERIALIZABLE.

С "Режимы блокировки"

Общие замки

... других нет транзакции могут изменить данные, в то время как общие (S) блокировки существуют на ресурс. Общие (S) замки на ресурс выпущен, как только операция чтения завершается, если только уровень изоляции транзакции установлен на повторяемое чтение или выше, или подсказка блокировки используется для сохранения общие (S) блокировки на время сделка.

Итак: общая блокировка запрещает запись и может быть сохранена, сделав ее SERIALIZABLE

1 голос
/ 04 июня 2010

ЗАМОК

Указывает, что блокировка берется для таблицы и удерживается до конца оператора. Если данные читаются, используется общая блокировка. Если данные изменяются, используется эксклюзивная блокировка. Если также указано HOLDLOCK, блокировка общей таблицы удерживается до конца транзакции.

При использовании с поставщиком массовых наборов строк OPENROWSET для импорта данных в таблицу без индексов TABLOCK позволяет нескольким клиентам одновременно загружать данные в целевую таблицу с оптимизированной регистрацией и блокировкой.

Взято из: http://msdn.microsoft.com/en-us/library/ms187373(SQL.90).aspx

...