Типы управления одновременным доступом
Теория управления одновременным доступом предлагает два способа осуществления управления:
- Пессимистичное управление
Система блокировок не допускает, чтобы изменение данных одними пользователями влияло на других пользователей. После того как действие пользователя приводит к блокировке, до тех пор пока инициатор ее не снимет, другие пользователи не могут выполнять действия, которые могут вызвать конфликт с блокировкой. Это называется пессимистичным управлением, поскольку в основном применяется в средах с большим количеством конфликтов данных, где затраты на защиту данных с помощью блокировок меньше затрат на откат изменений в случае конфликтов одновременного доступа. - Оптимистичное управление
При оптимистическом управлении пользователи не блокируют данные на период чтения. Когда пользователь обновляет данные, система проверяет, вносил ли другой пользователь в них изменение после считывания. Если другой пользователь изменял данные, возникает ошибка. Как правило, при получении сообщения об ошибке пользователь откатывает изменения и начинает процесс заново. Это называется оптимистичным управлением, поскольку в основном применяется в средах с небольшим количеством конфликтов данных, где затраты на периодический откат транзакции меньше затрат на блокировку данных при считывании.
Microsoft SQL Server поддерживает ряд средств управления одновременным доступом. Пользователи задают тип управления посредством выбора уровней изоляции транзакций.
Режимы блокировки
Для обеспечения безопасного одновременного доступа транзакций к ресурсам компонент Microsoft SQL Server Database Engine блокирует ресурсы с помощью различных режимов блокировки.
В следующей таблице показаны режимы блокировки ресурсов, применяемые компонентом Database Engine.
Режим блокировки | Описание |
Совмещаемая блокировка (S) | Используется для операций считывания, которые не меняют и не обновляют данные, такие как инструкция SELECT. Данный тип блокировки реализует пессимистичное управление одновременным доступом, эту блокировку могут одновременно захватывать несколько транзакций читающие данные, но транзакции изменяющие данные не могут получить на них блокировку до тех пор, пока кем-либо удерживается совмещаемая блокировка чтения. |
Блокировка обновления (U) | Применяется к тем ресурсам, которые потенциально могут быть обновлены транзакцией. Данный тип блокировки может захватываться только одной транзакцией, при этом, если транзакция действительно обновляет данные, блокировка преобразуется в Монопольную. Использование блокировки обновления позволяет избежать возникновения взаимоблокировки, когда несколько сеансов считывают данные используя Совмещаемую блокировку, а затем пытаются получить Монопольную блокировку для обновления данных. |
Монопольная блокировка (Х) | Данный тип блокировки запрещает транзакциям одновременный доступ к ресурсу и используется для операций модификации данных, таких как инструкции INSERT, UPDATE или DELETE. Гарантирует, что несколько обновлений не будет выполнено одновременно для одного ресурса, при этом операции считывания из других транзакций будут допускаться только при наличии подсказки NOLOCK или уровня изоляции обеспечивающего доступ для чтения к нефиксированным данным. |
Блокировка с намерением | Используется для создания иерархии блокировок. Типы намеренной блокировки: с намерением совмещаемого доступа (IS), с намерением монопольного доступа (IX), а также совмещаемая с намерением монопольного доступа (SIX). |
Блокировка схемы | Используется во время выполнения операции, зависящей от схемы таблицы. Пока удерживается блокировка изменения схемы, одновременный доступ к таблице запрещен, то есть любые операции вне блокировки изменения схемы будут запрещены до снятия блокировки. Существует два типа блокировки схем: блокировка изменения схемы (Sch-S) и блокировка стабильности схемы (Sch-M). |
Блокировка массового обновления (BU) | Используется, если выполняется массовое копирование данных в таблицу и указана подсказка TABLOCK. Данный тип блокировки позволяет поддерживать несколько одновременных потоков массовой загрузки данных в одну и ту же таблицу и при этом запрещать доступ к таблице любым другим процессам, отличным от массовой загрузки данных. |
Блокировка диапазона ключей | Защищает диапазон строк, неявно включенный в набор записей, считываемый инструкцией языка Transact-SQL. На время блокировки диапазона ключей конкурентные транзакции не могут изменить данные таблицы таким образом, что в первоначально полученном запросом наборе строк пропадут или появятся новые строки. |
Совмещаемые блокировки
Данный тип блокировки реализует пессимистичное управление одновременным доступом, эту блокировку могут одновременно захватывать несколько транзакций читающие данные, но транзакции изменяющие данные не могут получить на них блокировку до тех пор, пока кем-либо удерживается совмещаемая блокировка чтения. Совмещаемые блокировки (S) ресурса снимаются по завершении операции считывания, если только уровень изоляции транзакции не установлен на повторяющееся чтение или более высокий уровень, а также если совмещаемые блокировки (S) не продлены на все время транзакции с помощью подсказки блокировки.
Блокировки обновления
Применяется к тем ресурсам, которые потенциально могут быть обновлены транзакцией. Данный тип блокировки может захватываться только одной транзакцией, при этом, если транзакция действительно обновляет данные, блокировка преобразуется в Монопольную.
Использование блокировки обновления позволяет избежать возникновения взаимоблокировки, когда несколько сеансов считывают данные используя Совмещаемую блокировку, а затем пытаются получить Монопольную блокировку для обновления данных. Например, если две транзакции запрашивают совмещаемую блокировку на ресурс и затем пытаются одновременно обновить данные, то одна из транзакций пытается преобразовать блокировку в монопольную (X). Преобразование совмещаемой блокировки в монопольную потребует некоторого времени, поскольку монопольная блокировка для одной транзакции несовместима с совмещаемой блокировкой для другой транзакции. Начнется ожидание блокировки. Вторая транзакция попытается получить монопольную (X) блокировку для обновления. Поскольку обе транзакции выполняют преобразование в монопольную (X) блокировку и при этом каждая из транзакций ожидает, пока вторая снимет совмещаемую блокировку, то в результате возникает взаимоблокировка.
Монопольные блокировки
Монопольная (X) блокировка запрещает транзакциям одновременный доступ к ресурсу и гарантирует, что несколько обновлений не будет выполнено одновременно для одного ресурса, при этом операции считывания из других транзакций будут допускаться только при наличии подсказки NOLOCK или уровня изоляции обеспечивающего доступ для чтения к нефиксированным данным.
Изменяющие данные инструкции, такие как INSERT, UPDATE или DELETE, соединяют как операции изменения, так и операции считывания. Чтобы выполнить необходимые операции изменения данных, инструкция сначала должна получить соответствующие данные с помощью операций считывания. Например, инструкция UPDATE может изменять строки в одной таблице, основанной на соединении данных из другой таблицы. В этом случае инструкция UPDATE кроме монопольной блокировки обновляемых строк запрашивает также совмещаемые блокировки для строк, считываемых в соединенной таблице.
Блокировки с намерением
В компоненте Database Engine блокировки с намерением применяются для защиты размещения совмещаемой (S) или монопольной (X) блокировки ресурса на более низком уровне иерархии. Блокировки с намерением должны захватываться до блокировок более низкого уровня, то есть они обозначают намерение поместить блокировку на более низком уровне.
Блокировка с намерением выполняет две функции:
· предотвращает изменение ресурса более высокого уровня другими транзакциям таким образом, что это сделает недействительной блокировку более низкого уровня;
· повышает эффективность компонента Database Engine при распознавании конфликтов блокировок на более высоком уровне гранулярности.
Например, в таблице требуется блокировка с намерением совмещаемого доступа до того, как для страниц или строк этой таблицы будет запрошена совмещаемая (S) блокировка. Если задать блокировку с намерением на уровне таблицы, то другим транзакциям будет запрещено получать монопольную (X) блокировку для таблицы, содержащей эту страницу.
Компонент Database Engine проверяет наличие блокировок с намерением только на уровне таблицы, чтобы определить, может ли транзакция безопасно получить для этой таблицы совмещаемую блокировку. Благодаря этому нет необходимости проверять блокировки в каждой строке и на каждой странице, чтобы убедиться, что транзакция может заблокировать всю таблицу, это позволяет добиться большей производительности.
В состав блокировок с намерением входят блокировка с намерением совмещаемого доступа (IS), блокировка с намерением монопольного доступа (IX), а также совмещаемая блокировка с намерением монопольного доступа (SIX).
Режимы блокировки с намерениями:
Режим блокировки | Описание |
Блокировка с намерением совмещаемого доступа (IS) | Защищает запрошенные или полученные совмещаемые блокировки на некоторых (но не на всех) ресурсах на более низком уровне иерархии. |
Блокировка с намерением монопольного доступа (IX) | Защищает запрошенные или полученные монопольные блокировки на некоторых (но не на всех) ресурсах на более низком уровне иерархии. Режим IX является расширенным режимом IS, кроме того, он защищает запрос на совмещаемые блокировки на ресурсах более низкого уровня. |
Совмещаемая блокировка с намерением монопольного доступа (SIX) | Защищает запрошенные или полученные совмещаемые блокировки на всех ресурсах более низкого уровня иерархии, а также блокировки с намерением на некоторых (но не всех) ресурсах более низкого уровня. На ресурсах верхнего уровня допускаются одновременные блокировки IS. Например, запрос блокировки SIX для таблицы запрашивает блокировку с намерением монопольного доступа для всех изменяемых страниц и монопольную блокировку изменяемых строк. Одновременно для одного ресурса может быть установлена только одна блокировка SIX, что предотвращает обновление ресурса другими транзакциями, хотя эти транзакции могут считывать данные с ресурсов более низкого уровня в иерархии, получая блокировкиIS уровня таблицы. |
Блокировка с намерением обновления (IU) | Защищает запрошенные или полученные блокировки обновления на всех ресурсах более низкого уровня в иерархии. Блокировки IU применяются только на страничных ресурсах. Если выполняется операция обновления, то блокировки IU преобразуются в IX. |
Совмещаемая блокировка с намерением обновления (SIU) | Сочетание блокировок S и IU в результате раздельного запрашивания этих блокировок и одновременного удержания их обеих. |
Блокировка обновления с намерением монопольного доступа (UIX) | Сочетание блокировок U и IX в результате раздельного запрашивания этих блокировок и одновременного удержания их обеих. |
Блокировки схем
В компоненте Database Engine блокировка изменения схемы (Sch-M) применяется с операциями языка определения схемы (DDL) для таблиц, например при добавлении столбца или очистке таблицы. Пока удерживается блокировка изменения схемы, одновременный доступ к таблице запрещен, то есть любые операции вне блокировки изменения схемы будут запрещены до снятия блокировки.
Существует два типа блокировки схем:
· Блокировка изменения схемы (Sch-M) применяется с некоторыми операциями языка обработки данных, например усечением таблиц, чтобы предотвратить одновременный доступ к таблице.
· Блокировка стабильности схемы (Sch-S) применяется компонентом Database Engine при компиляции и выполнении запросов. Блокировка стабильности схемы (Sch-S) не влияет на блокировки транзакций, включая монопольные (X) блокировки, поэтому другие транзакции (даже транзакции с монопольной блокировкой (X) для таблицы) могут продолжать работу во время компиляции запроса. Однако, одновременные операции DDL и DML, которые запрашивают блокировки изменения схемы (Sch-M), над таблицей выполняться не могут.
Блокировки массового обновления
Блокировки массового обновления (BU) применяются компонентом Database Engine при массовом копировании данных в таблицу. Данный тип блокировки позволяет поддерживать несколько одновременных потоков массовой загрузки данных в одну и ту же таблицу и при этом запрещать доступ к таблице любым другим процессам, отличным от массовой загрузки данных.
Блокировки диапазона ключа
Блокировки диапазона ключа защищает диапазон строк, неявно включенный в набор записей, считываемый инструкцией языка Transact-SQL. На время блокировки диапазона ключей конкурентные транзакции не могут изменить данные таблицы таким образом, что в первоначально полученном запросом наборе строк пропадут или появятся новые строки.
Использование различных режимов блокировки позволяет обеспечить высокопроизводительный конкурентный доступ к данным, не нарушая их целостность. За счет использования подсказок в запросах и возможности выбора желаемого уровня изоляции транзакций, пользователи имеют возможность гранулярного управления достоверностью получаемых данных и скоростью доступа к ним.
Взаимоблокировка
Взаимоблокировка возникает, когда две и более задач постоянно блокируют друг друга в ситуации, когда у каждой задачи заблокирован ресурс, который пытаются заблокировать другие задачи. Например:
- Транзакция А создает общую блокировку строки 1.
- Транзакция Б создает общую блокировку строки 2.
- Транзакция А теперь запрашивает монопольную блокировку строки 2 и блокируется до того, как транзакция Б закончится и освободит общую блокировку строки 2.
- Транзакция Б теперь запрашивает монопольную блокировку строки 1 и блокируется до того, как транзакция A закончится и освободит общую блокировку строки 1.
Транзакция А не может завершиться до того, как завершится транзакция Б, а транзакция Б заблокирована транзакцией А. Такое условие также называется цикличной зависимостью: транзакция А зависит от транзакции Б, а транзакция Б зависит от транзакции А и этим замыкает цикл.
Обе транзакции находятся в состоянии взаимоблокировки и будут всегда находиться в состоянии ожидания, если взаимоблокировка не будет разрушена внешним процессом. Монитор взаимоблокировок компонента Microsoft SQL Server Database Engine периодически проверяет задачи на состояние взаимоблокировки. Если монитор обнаруживает цикличную зависимость, то выбирается одна задача, для которой транзакция будет завершена с ошибкой. Это позволяет другой задаче завершить свою транзакцию. Позднее приложение может повторно выполнить транзакцию, которая завершилась с ошибкой, обычно после того как другая транзакция (бывшая в состоянии взаимоблокировки) завершится.
На рисунке транзакция Т1 зависит от транзакции Т2 для ресурса блокировки таблицы Деталь. Аналогично транзакция Т2 зависит от транзакции Т1 для ресурса блокировки таблицы Поставщик. Так как эти зависимости из одного цикла, возникает взаимоблокировка транзакций T1 и T2.