Таблок против Таблока - PullRequest
70 голосов
/ 24 февраля 2011

В чем разница между TABLOCK и TABLOCKX http://msdn.microsoft.com/en-us/library/ms187373.aspx указывает, что TABLOCK является общей блокировкой, а TABLOCKX является эксклюзивной блокировкой. Первый, может быть, только своего рода индексная блокировка? И какова концепция совместного использования блокировки?

Ответы [ 3 ]

94 голосов
/ 25 февраля 2011

Большая разница, TABLOCK попытается захватить "общие" блокировки и TABLOCKX эксклюзивные блокировки.

Если вы находитесь в транзакции и захватываете эксклюзивную блокировку на столе, например:

SELECT 1 FROM TABLE WITH (TABLOCKX)

Никакие другие процессы не смогут получить любые блокировки таблицы, что означает, что все запросы, пытающиеся связаться с таблицей, будут заблокированы, пока транзакция не будет зафиксирована.

TABLOCK захватывает только общую блокировку, общие блокировки снимаются после выполнения оператора, если ваша транзакция изолирована READ COMMITTED (по умолчанию). Если ваш уровень изоляции выше , например: SERIALIZABLE, общие блокировки удерживаются до конца транзакции.


Общие замки, хммм, общие. Это означает, что 2 транзакции могут одновременно считывать данные из таблицы, если они обе удерживают в таблице блокировку S или IS (через TABLOCK). Однако, если transaction A содержит общую блокировку для таблицы, transaction B не сможет получить эксклюзивную блокировку, пока не будут сняты все общие блокировки. Читайте о том, какие замки совместимы с какими в MSDN .


Обе подсказки приводят к тому, что база данных обходится, принимая более детальные блокировки (например, блокировки на уровне строк или страниц). В принципе, более гранулярные блокировки обеспечивают лучший параллелизм. Так, например, одна транзакция может обновлять строку 100 в вашей таблице и другую строку 1000, одновременно из двух транзакций (это сложно сделать с блокировками страниц, но давайте пропустим это).

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

Как правило, вы не будете использовать TABLOCK или TABLOCKX, если вам это абсолютно не нужно для какого-то крайнего случая.

4 голосов
/ 24 февраля 2011

Довольно старая статья о mssqlcity пытается объяснить типы блокировок:

Общие блокировки используются для операций, которые не изменяют или не обновляют данные, таких как оператор SELECT.

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

Эксклюзивные блокировки используются для операций модификации данных, таких как UPDATE, INSERT или DELETE.

То, что не обсуждается, это Intent (который в основном является модификатором для этих типов блокировок). Преднамеренные (общие / исключительные) блокировки - это блокировки, удерживаемые на более высоком уровне, чем реальные блокировки. Так, например, если ваша транзакция имеет блокировку X для строки, она также будет иметь блокировку IX на уровне таблицы (что не позволяет другим транзакциям пытаться получить несовместимую блокировку на более высоком уровне таблицы (например, схему). блокировка модификации) до тех пор, пока ваша транзакция не завершится или не откатится).


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

2 голосов
/ 06 января 2017

Это скорее пример, где TABLOCK не работал для меня, а TABLOCKX работал.

У меня есть 2 сеанса, оба используют уровень изоляции READ COMMITTED по умолчанию:

Сессия 1 - это явная транзакция, которая копирует данные со связанного сервера в набор таблиц в базе данных, и ее запуск занимает несколько секунд. [Пример, это удаляет Вопросы] Сессия 2 - это оператор вставки, который просто вставляет строки в таблицу, в которую Сессия 1 не вносит изменений. [Например, он вставляет ответы].

(На практике несколько сеансов одновременно вставляют несколько записей в таблицу, пока сеанс 1 выполняет свою транзакцию).

Сессия 1 должна запросить таблицу, в которую вставляет Сессия 2, потому что она не может удалить записи, которые зависят от записей, которые были добавлены Сессией 2. [Пример: Удалить вопросы, на которые не было ответа].

Итак, пока сеанс 1 выполняется, а сеанс 2 пытается вставить, сеанс 2 каждый раз теряется в тупике.

Итак, оператор удаления в сеансе 1 может выглядеть примерно так: УДАЛИТЬ TBLA ИЗ TBLQ ЛЕВЫЙ РЕЙТИНГ TBLX на ... СЛЕВА ПРИСОЕДИНЯЙТЕСЬ К tblA ON ON tblQ.Qid = tblA.Qid ГДЕ ... a.QId НУЛЬ и ...

Кажется, что тупик вызван конфликтом между запросами tblA, когда Сессия 2, [3, 4, 5, ..., n] пытается вставить в tblA.

В моем случае я мог бы изменить уровень изоляции транзакции сеанса 1 на SERIALIZABLE. Когда я сделал это: Менеджер транзакций отключил поддержку удаленных / сетевых транзакций.

Итак, я мог бы следовать инструкциям в принятом ответе, чтобы обойти его: Менеджер транзакций отключил поддержку удаленных / сетевых транзакций

Но а) меня не устраивало изменение уровня изоляции на SERIALIZABLE, в первую очередь - предположительно, это ухудшает производительность и может иметь другие последствия, которые я не учел, б) не понимал, почему это внезапно вызвало в транзакции возникла проблема при работе на связанных серверах, и c) не знаю, какие возможные дыры я мог бы открыть, разрешив доступ к сети.

Казалось, что в очень большой транзакции было только 6 запросов, которые вызывают проблемы.

Итак, я читал о TABLOCK и TabLOCKX.

Я не был кристально ясен в различиях, и не знал, сработает ли один из них. Но казалось, что так и будет. Сначала я попробовал TABLOCK, и это, похоже, не имело никакого значения. Конкурирующие сессии вызывали одинаковые тупики. Затем я попробовал TABLOCKX, и больше никаких тупиков.

Итак, в шести местах все, что мне нужно было сделать, это добавить WITH (TABLOCKX).

Итак, оператор удаления в сеансе 1 может выглядеть примерно так: УДАЛИТЬ ТАБЛИЦУ ОТ ТАБЛИЦЫ q ВЛЕВО СОЕДИНЯТЬ ТАБЛИЦЫ x на ... СЛЕДУЕТ ПРИСОЕДИНИТЬСЯ К tblA a С (TABLOCKX) ON tblQ.Qid = tblA.Qid ГДЕ ... a.QId НУЛЬ и ...

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...