Почему табличный хинт XLOCK не работает?
Пересказ статьи DANIEL JANIK. Why is the XLOCK table hint broken?
Поговорим о том, для чего служит XLOCK. XLOCK - это табличный хинт, который может использоваться в запросе, чтобы наложить эксклюзивную блокировку на ресурсы, к которым обращается запрос. Он может быть весьма опасен, поскольку эксклюзивная блокировка на таблицу или раздел может вызвать значительную потерю производительности.
Мы сделаем запрос единственной строки, используя первичный ключ таблицы. Начнем транзакцию с последующим запросом единичной строки, использующим хинт XLOCK.
Затем посмотрим sys.dm_tran_locks, чтобы проверить, что строка имеет эксклюзивную блокировку. Это можно увидеть в столбце request_mode, где "X" означает эксклюзивная.
Поскольку это эксклюзивная блокировка, она должна гарантировать, что все другие попытки получить доступ к данным должны блокироваться. Т.е. блокируются выборки, вставки, обновления и удаления. Единственный способ получить доступ при эксклюзивной блокировке, это грязное чтение при использовании табличного хинта NOLOCK.
Наконец, выполните тот же запрос без XLOCK в другой сессии, и вы увидите, что XLOCK совершенно не работает! Ну не так быстро...
Табличный хинт XLOCK можно считать ненадежным. Это обусловлено тем, что движок SQL может игнорировать этот хинт, если данные, к которым требуется доступ, не изменились с момента самой старой открытой транзакции. Заметим, что если бы оба наши запроса использовали XLOCK, второй запрос был бы блокирован.
Из-за подобных ситуаций я не рекомендую использование хинтов; хотя, как и все в мире баз данных, это зависит от...
Что если ситуация требует наложить эксклюзивную блокировку с оператором SELECT?
Сначала я спрошу, почему необходима блокировка XLOCK? Если архитектурно, то как мы до этого дошли? Плохой проект может привести к необходимости плохих решений.
Если XLOCK действительно необходим, то сочетание его с PAGLOCK будет блокировать операторы SELECT для строки. Это связано с тем, что IX (намеренная блокировка) страницы во втором запросе будет заблокирована X-блокировкой страницы из первого запроса.
Затем посмотрим sys.dm_tran_locks, чтобы проверить, что строка имеет эксклюзивную блокировку. Это можно увидеть в столбце request_mode, где "X" означает эксклюзивная.
Поскольку это эксклюзивная блокировка, она должна гарантировать, что все другие попытки получить доступ к данным должны блокироваться. Т.е. блокируются выборки, вставки, обновления и удаления. Единственный способ получить доступ при эксклюзивной блокировке, это грязное чтение при использовании табличного хинта NOLOCK.
Наконец, выполните тот же запрос без XLOCK в другой сессии, и вы увидите, что XLOCK совершенно не работает! Ну не так быстро...
Табличный хинт XLOCK можно считать ненадежным. Это обусловлено тем, что движок SQL может игнорировать этот хинт, если данные, к которым требуется доступ, не изменились с момента самой старой открытой транзакции. Заметим, что если бы оба наши запроса использовали XLOCK, второй запрос был бы блокирован.
Из-за подобных ситуаций я не рекомендую использование хинтов; хотя, как и все в мире баз данных, это зависит от...
Что если ситуация требует наложить эксклюзивную блокировку с оператором SELECT?
Сначала я спрошу, почему необходима блокировка XLOCK? Если архитектурно, то как мы до этого дошли? Плохой проект может привести к необходимости плохих решений.
Если XLOCK действительно необходим, то сочетание его с PAGLOCK будет блокировать операторы SELECT для строки. Это связано с тем, что IX (намеренная блокировка) страницы во втором запросе будет заблокирована X-блокировкой страницы из первого запроса.
Обратные ссылки
Автор не разрешил комментировать эту запись
Комментарии
Показывать комментарии Как список | Древовидной структурой