Принципы работы блокировок в базе данных
Принципы работы блокировок
Блокировка — это объект, с помощью которого программы показывают зависимость пользователя от ресурса. Программы запрещают другим пользователям выполнять над ресурсами операции, которые негативно влияют на зависимость пользователя, владеющего блокировкой, от этого ресурса. Блокировки управляются внутрисистемными механизмами, они устанавливаются и снимаются в зависимости от действий пользователя.
Блокировки применяются в БД на разных уровнях. Их устанавливают для строк, страниц, ключей, диапазонов ключей, индексов, таблиц или баз данных. SQL Server динамически определяет уровень блокировки для каждого оператора Transact-SQL. Уровень, на котором задается блокировка, может варьироваться для разных объектов в пределах одного запроса. Пользователям не нужно определять уровень блокировки, администраторы также не должны заниматься его настройкой. Каждый экземпляр SQL Server гарантирует, что блокировки, действующие на одном уровне, не нарушат блокировок, установленных на другом уровне.
Существуют несколько видов блокировок: разделяемые, обновления, эксклюзивная, предварительные и блокировки схемы. Вид блокировки показывает уровень зависимости соединения от заблокированного объекта. SQL Server контролирует взаимодействие блокировок разных видов.
Lock mode |
Description |
Разделяемая
Shared (S) |
Используется для операций, не изменяющих данные, например Select |
Обновления
Update (U) |
Используется на ресурсах, которые могут быть обновлены. Предотвращает коллизии, когда несколько процессов читают, блокируют и потенциально могут изменить ресурсы позднее |
Экслюзивная
Exclusive (X) |
Используется для действий операций модификации данных. Гарантирует, что несколько процессов не смогут изменять один и тот же ресурс одновременно |
Предварительная
Intent |
Используется для установки иерархии блокировок. Типы предварительных блокировок: предварительная разделяемая (IS), предварительная эксклюзивная (IX) и предварительная разделяемо-эксклюзивная (SIX) |
Schema | Используется когда выполняется операция, зависимая от схемы таблиц. Разновидности: модификации схемы (SCH-M) и стабильности схемы (SCH-S) |
Bulk Update (BU) | Используется в случае операций пакетного обновления данных в таблице и указано предложение TABLOCK |
При разделяемой блокировке, конкурирующие процессы могут читать данные с тех же ресурсов, но не могут изменять эти ресурсы. Освобождение блокировки происходит после того, как инициирующий блокировку процесс прочитал данные ресурса, если только уровень изоляции не установлен равным Repeatable Read или Serializable.
Типичной ситуацией, когда используется блокировка обновления, является ситуация, когда процесс модификации сначала читает ресурс (строку или страницу), устанавливая разделяемую блокировку, а затем изменяет ресурс, что требует изменения типа блокировки на эксклюзивный. Если две транзакции пытаются изменить один и тот же ресурс, то сначала первая транзакция, начавшая операцию модификации меняет тип блокировки на эксклюзивный, а вторая транзакция снимает свою блокировку и ожидает пока первая не завершит операцию обновления ресурса. Это происходит потому, что две транзакции не могут одновременно редактировать один и тот же ресурс. Если транзакция модифицирует ресурс, используя блокировку обновления, то блокировка становится сначала эксклюзивной, а после обновления разделяемой.
Эксклюзивные блокировки предотвращают любой доступ к ресурсу другим процессам.
Предварительная блокировка означает, что процесс желает наложить блокировку (S или X) на один из ресурсов ниже по иерархии ресурсов. Например, предварительная блокировка на уровне таблицы означает, что транзакция будет пытаться накладывать блокировку на страницах или строках данной таблицы. Установка предварительной табличной блокировки может препятствовать установке эксклюзивной блокировки другой транзакции на страницу, принадлежащей данной таблице. Предварительные блокировки разделяются на 3 категории: предварительная эксклюзивная, предварительная разделяемая и предварительная разделяемо- эксклюзивная.
Предварительная разделяемая блокировка означает, что транзакция намерена наложить разделяемую блокировку на некоторое количество (но не на все) объектов ниже по иерархии.
Предварительная эксклюзивная – транзакция намерена изменить некоторое количество ресурсов ниже в иерархии.
Предварительная эксклюзивно-разделяемая, означает, что транзакция намерена прочитать все ресурсы ниже в иерархии и некоторые из них обновить. При этом возможно наложение другой транзакцией IS блокировки. Однако не может быть двух одновременных SIX блокировок на одном объекте.
SCH—M блокировка накладывается в случае выполнения DDL оператора
SCH—S блокировка используется при компиляции запросов. Эти блокировки не запрещают наложения другими транзакциями никаких других блокировок, даже эксклюзивных.
Блокировки пакетного обновления используются в случае пакетной загрузки данных в таблицу или когда используется фраза TABLOCK. Блокировки пакетного обновления позволяют работать транзакциям, загружающим массивы данных в таблицу и предотвращающие доступ другим транзакциям к БД.
В SQL Server предусмотрен алгоритм для обнаружения взаимоблокировок двух соединений. Если экземпляр SQL Server обнаружил взаимоблокировку, то одна из транзакций будет прекращена, что позволит продолжить выполнение другой.
Обработка взаимоблокировок
Взаимоблокировка возникает, когда два или более потоков, конкурирующих за ресурс, становятся взаимозависимыми. Взаимоблокировка возможна не только в РСУБД, но и в любой многопоточной системе, где поток способен захватить один или несколько ресурсов (например, блокировку). Если захватываемый ресурс в настоящее время принадлежит другому потоку, то первый поток ожидает освобождения целевого ресурса его владельцем. В такой ситуации говорят о зависимости ожидающего потока от потока, владеющего некоторым ресурсом.
Если поток-владелец пытается захватить другой ресурс, принадлежащий в настоящее время ожидающему потоку, возникает взаимоблокировка. Ни один поток не может освободить задействованные ресурсы, пока их транзакции не будут зафиксированы или отменены, а этого не случится, поскольку оба потока ожидают освобождения ресурса другим потоком.
Минимизация числа взаимоблокировок
Хотя полностью избежать взаимоблокировок не удается, их число можно существенно уменьшить, чтобы увеличить пропускную способность при обработке транзакций и снизить системные издержки, поскольку меньше транзакций будут подвергаться откату с отменой всей выполненной ими работы. Кроме того, уменьшится число транзакций, повторно переданных приложениями на сервер из-за отката в результате взаимоблокировок.
Чтобы минимизировать число взаимоблокировок, необходимо придерживаться следующих правил:
• не изменять порядок обращения к объектам;
• избегать взаимодействия с пользователем во время транзакции;
• следить, чтобы транзакции были короткими и не выходили за пределы одного пакета;
• использовать низкие уровни изоляции;
• использовать привязанные соединения.
Добавить комментарий