Блокировка диапазона ключей

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

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

Блокировка диапазона ключей применятся к индексу, указывая начальное и конечное значения ключа. Данная блокировка предотвращает все попытки вставки, обновления или удаления строк со значением ключа, находящимся в этом диапазоне, поскольку для выполнения этих операций потребуется получение блокировки индекса. Например, сериализуемая транзакция выполняет инструкцию SELECT, считывающую все строки, ключевые значения которых лежат между 'AAA' и 'CZZ'. Блокировка диапазона ключей для значений ключа между 'AAA' и 'CZZ' запрещает другим транзакциям вставлять строки со значениями ключа, входящими в этот диапазон, например запрещаются значения ключа 'ADG', 'BBD' и 'CAL'.

Режимы блокировки диапазона ключей

Блокировки диапазона ключей содержат и компонент диапазона, и компонент строки, которые задаются в формате диапазона строк:

  • Компонент диапазона соответствует режиму блокировки, защищающему диапазон между любыми двумя последовательными элементами индекса.

  • Компонент строки соответствует режиму блокировки, защищающему сами элементы индекса.

  • Режим соответствует применяемому соединенному режиму блокировки. Режимы блокировки диапазона ключей состоят из двух частей. Первая представляет собой тип блокировки, используемой для блокировки диапазона индекса (RangeT), а вторая представляет тип блокировки, используемой для блокировки конкретных ключей(K). Эти две части соединены дефисом (-), например RangeT-K.

    Диапазон

    Строка

    Режим

    Описание

    RangeS

    S

    RangeS-S

    Совмещаемая блокировка диапазона — совмещаемая блокировка ресурса; упорядочиваемый просмотр диапазона.

    RangeS

    U

    RangeS-U

    Совмещаемая блокировка диапазона — блокировка обновления ресурса; упорядочиваемый просмотр обновлений.

    RangeI

    NULL

    RangeI-N

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

    RangeX

    X

    RangeX-X

    Монопольная блокировка диапазона, монопольная блокировка ресурса; используется при обновлении ключа в диапазоне.

ПримечаниеПримечание

Внутренней нулевой режим блокировки совместим со всеми другими режимами блокировки.

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

Полученный ранее режим

Запрашиваемый режим

S

U

X

RangeS-S

RangeS-U

RangeI-N

RangeX-X

Совмещаемая (S)

Да

Да

Нет

Да

Да

Да

Нет

Обновления (U)

Да

Нет

Нет

Да

Нет

Да

Нет

Монопольная (Х)

Нет

Нет

Нет

Нет

Нет

Да

Нет

RangeS-S

Да

Да

Нет

Да

Да

Нет

Нет

RangeS-U

Да

Нет

Нет

Да

Нет

Нет

Нет

RangeI-N

Да

Да

Да

Нет

Нет

Да

Нет

RangeX-X

Нет

Нет

Нет

Нет

Нет

Нет

Нет

Блокировки преобразования

При пересечении двух блокировок диапазона ключей создаются блокировки преобразования.

Блокировка 1

Блокировка 2

Блокировка преобразования

S

RangeI-N

RangeI-S

U

RangeI-N

RangeI-U

X

RangeI-N

RangeI-X

RangeI-N

RangeS-S

RangeX-S

RangeI-N

RangeS-U

RangeX-U

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

Упорядочиваемое сканирование диапазона, одноэлементная выборка, удаление и вставка

Блокировка диапазона ключей гарантирует, что следующие операции являются упорядочиваемыми:

  • Запрос просмотра диапазона

  • Одноэлементная выборка несуществующей строки

  • Операция удаления

  • Операция вставки

Для получения блокировки диапазона ключей должны выполняться следующие условия:

  • Должен быть установлен уровень изоляции транзакций SERIALIZABLE.

  • Обработчик запросов должен использовать индекс при применении предиката фильтрации по диапазону. Например, предложение WHERE инструкции SELECT может установить условие по диапазону с помощью следующего предиката: СтолбецX BETWEEN N**'AAA'** AND N**'CZZ'**. Блокировка диапазона ключей может быть получена лишь в случае, если СтолбецX входит в ключ индекса.

Примеры

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

Таблица базы данных с иллюстрацией сбалансированного дерева индекса

Запрос просмотра диапазона

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

SELECT name
    FROM mytable
    WHERE name BETWEEN 'A' AND 'C';

Блокировка диапазона ключей устанавливается на элементы индекса, соответствующие диапазону строк данных, имена которых находятся между значениями Adam и Dale, что приводит в результате к запрету добавления или удаления новых строк, выбранных в предыдущем запросе. Хотя первым именем диапазона является Adam, блокировка диапазона ключей в режиме RangeS-S по этому элементу индекса гарантирует, что не будут добавляться новые имена, начинающиеся с буквы А, например Abigail. Аналогично блокировка диапазона ключей в режиме RangeS-S по элементу индекса для имени Dale дает гарантию того, что не будут добавляться новые имена после Carlos, начинающиеся с буквы C, например Clive.

ПримечаниеПримечание

Число установленных блокировок RangeS-S равно n+1, где n — это число строк, удовлетворяющих запросу.

Одноэлементная выборка несуществующих данных

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

SELECT name
    FROM mytable
    WHERE name = 'Bill';

На элемент индекса устанавливается блокировка диапазона ключей, соответствующая именам от Ben до Bing, так как имя Bill было бы вставлено между этими соседними элементами индекса. Блокировка диапазона ключей режима RangeS-S применяется к элементу индекса Bing. Это предотвращает вставку другими транзакциями значений между элементами индекса Ben и Bing, например запрещается вставка значения Bill.

Операция удаления

При удалении значения из транзакции диапазон, к которому относится значение, не должен быть заблокирован во время существования транзакции, которая выполняет удаление. Блокировка удаляемого значения ключа до конца выполнения транзакции достаточна для обеспечения возможности сериализации. Например, рассмотрим эту инструкцию DELETE:

DELETE mytable
    WHERE name = 'Bob';

Монопольная (X) блокировка установлена на элемент индекса, соответствующий имени Bob. Другие транзакции могут добавлять или удалять значения, находящиеся перед удаленным значением Bob или после него. Однако попытка любой транзакции прочесть, вставить или удалить значение Bob блокируется до фиксации или отката транзакции, которая выполнила удаление.

Удаление диапазона можно выполнить, используя три базовых режима блокировки: блокировки строки, страницы или таблицы. Стратегия блокировки строки, страницы или таблицы либо выбирается автоматически оптимизатором запросов, либо задается пользователем с помощью подсказок блокировки ROWLOCK, PAGLOCK и TABLOCK. При использовании подсказок PAGLOCK или TABLOCK при удалении всех входящих в страницу строк компонент Database Engine немедленно освобождает память, занимаемую страницей индекса. При использовании подсказки ROWLOCK, напротив, все удаленные строки лишь отмечаются как удаленные, со страницы индекса их удаляет позже выполняющаяся в фоновом режиме задача.

Операция вставки

При вставке значения из транзакции диапазон, в который попадает значение, не должен быть заблокирован во время существования транзакции, выполняющей вставку. Блокировка вставленного значения ключа до конца выполнения транзакции достаточна для обеспечения возможности сериализации. Рассмотрим следующую инструкцию INSERT:

INSERT mytable VALUES ('Dan');

Для проверки диапазона блокировка диапазона ключей в режиме RangeI-N применяется к элементу индекса, соответствующему имени David. Если блокировка предоставляется, тогда вставляется значение Dan, и к этому значению применяется монопольная (X) блокировка. Блокировка диапазона ключей в режиме RangeI-N необходима только для проверки диапазона, поэтому она не поддерживается в течение всего времени существования выполняющей вставку транзакции. Другие транзакции могут вставлять или удалять значения, находящиеся перед вставленным значением Dan или после него. Однако попытка любой транзакции прочесть, вставить или удалить значение Dan будет блокироваться до отката или фиксации транзакции, которая выполнила вставку.