TABLOCK vs TABLOCKX


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

3 62

3 ответа:

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

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

SELECT 1 FROM TABLE WITH (TABLOCKX)

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

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


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


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

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

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

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

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

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

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

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


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

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

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

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

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

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

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

Итак, оператор delete в сеансе 1 может выглядеть примерно так: Удалить сведения калорифер tbla с tblQ левое соединение tblX на ... Слева присоединяйтесь к tblA A на tblQ.Qid = tblA.Qid ГДЕ... A. QId имеет значение NULL и ...

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

в моем случае я мог бы изменить уровень изоляции транзакции сеанса 1, чтобы быть СЕРИАЛИЗУЕМЫМ. когда я это: диспетчер транзакций отключил поддержку удаленных и сетевых транзакций.

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

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

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

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

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

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

Итак, оператор delete в сеансе 1 может выглядеть примерно так: Удалить сведения калорифер tbla с tblQ м левое соединение tblX X на ... Левое соединение tblA a с (TABLOCKX) на tblQ.Qid = tblA.Qid ГДЕ... A. QId имеет значение NULL и ...