Блокировки

dbstalker, 03 июня

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

Основные вопросы, рассматриваемые в данной статье:

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

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

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

Реализация блокирования в ORACLE уникальна и близка к совершенству.Блокировка – это механизм, используемый для управления одновременным доступом к общему ресурсу. Сервер ORACLE блокирует данные таблицы на уровне строк, но для обеспечения одновременного доступа к другим ресурсам используются блокировки и других уровней. Это наглядно видно для процедур: при выполнении в одной сессии хранимой процедуры, в другой сессии её тоже можно выполнять, но не изменять.

Основная цель блокировок - обеспечить целостность и согласованность данных при одновременном доступе к общим ресурсам.

Основные отличительные особенности СУРБД ORACLE при использовании механизма блокирования:

  • Транзакция – это хорошо
  • Фиксацию транзакции можно откладывать как угодно долго. Основное правило – фиксируйте транзакцию не раньше, чем его нужно по логике вашей программы.
  • Блокировки не являются ограниченным ресурсом. То есть удерживать блокировки можно сколь угодно долго.
  • Блокировка на уровне строк не приводит к дополнительным расходам ресурсов.
  • Ненужно повышать уровень блокирования.
  • Одновременный доступ к данным и их согласованность не противоречат друг другу.

Необходимость блокирования.

  • Потерянное изменение – одна из основных проблем баз данных. Как возникает такая проблема? Рассмотрим пример: Пользователь выбирает строку данных (адрес и телефон клиента), переходит в режим редактирования, меняет адрес и сохраняет изменения. Другой пользователь выбрал туже запись и в тоже время, что и первый пользователь, но зафиксировал свои изменения номера телефона этого же клиента позже, чем первый пользователь. В результате изменение адреса клиента первым пользователем потерялось.
  • Один пользователь изменяет данные в таблице, а другой в это время пытается удалить ту же таблицу.
  • Один пользователь пытается читать данные, которые в данный момент изменяются другим пользователем.

Обычно используется два метода блокирования: пессимистическое блокирование и оптимистическое.

Пессимистическое. Суть этого метода состоит в том, что мы перед изменением строки, её блокируем. То есть, для первого пользователя мы выбрали для просмотра строку, если пользователь надумал её отредактировать, мы повторно читаем строку сверяя все столбцы и блокируем запись ( select for update nowait). Если за этот промежуток времени изменений не было и запись незаблокирована другими пользователями, то необходимая запись будет выбрана и заблокирована первым пользователем. Если были зафиксированы изменения, произведенные другим пользователем, то запись не будет выбрана. Если запись заблокирована, мы получим ошибку ora-00054 Resource Buzy , и будем ждать, пока со строки не будет снята блокировка. После снятия блокировки нужно будет повторно запросить и заблокировать запись.

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

Оптимистическое. Суть этого метода состоит в том, что мы сохраняем и старое значение и новое значение полей и используем их при выполнении команды:

Update table
Set column1=:new_column1, column2=:new_column2, column3=:new_column3……
Where column1=:old_column1 and column2=:old_column2 and 
Column3=:old_column3…..

Если в результате строка изменена, то все отлично. Если ни одна строка не изменилась – кто-то уже изменил нашу строку, нужно принимать какое-то решение.

К этому методу есть небольшое замечание. Используя оператор update в таком виде как предложено, мы избегаем потери изменений, но возникает проблема зависания. Поэтому имеет смысл перед этим оператором выполнять команду select for update nowait.

Таким образом, при пессимистическом блокировании - сначала думаем , потом делаем, а при оптимистическом – сначала делаем, потом думаем.

Какой метод блокирования лучше? Том Кайт придерживается мнения, что в Oracle лучше использовать пессимистическое блокирование. У вас есть основания ему не верить? Он объясняет свою позицию так. При использовании пессимистического блокирования пользователь может быть уверен в том, что строка в его полном распоряжении, и никто другой её не изменит. Конечно, другие пользователи, которые также хотят изменить эту строку, вынуждены будут ждать освобождения строки. Но в любом случае, обновлять строку в конкретный момент времени может только один пользователь. К тому же, для просмотра любым пользователем наша строка остается доступной всегда.

Общие сведения о блокировках

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

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

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

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

Oracle гарантирует непротиворечивость данных на уровне оператора и на уровне транзакции.

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

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

Сегменты отката – основной инструмент, который обеспечивает непротиворечивость чтения. Вначале выполнения запроса фиксируется текущий номер SCN (назовем его SCN запроса). Когда происходит чтение блоков данных, то SCN блока сравнивается с SCN запроса. Если SCN блока оказался больше SCN запроса, то это значит, что блок был изменен после начала запроса. Поэтому данные будут выбираться из сегмента отката.

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

Блокирование в базе данных выполняют четыре DML оператора: insert, update, delete, select for update.

Использование оператора select for update никогда не приведет к зависанию, если вы добавите конструкцию nowait. Зависания не будет, приложение должно только сообщить о том, что строка уже заблокирована.

Оператор insert приводит к зависанию только в одном случае: когда два оператора insert хотят вставить строку с одним и тем же значение первичного ключа или с одним и тем же значением, которое нарушает ограничение уникальности. В этом случае, один сеанс буде заблокирован, пока другой не зафиксирует изменение. Эта проблема достаточно легко решается, если для генерации уникальных значений использовать последовательности.

Операторы update и delete могут спровоцировать зависание тогда, когда пробуете изменить строку, которая в данный момент уже кем-то заблокирована. Избежать этого можно, если использовать оператор select for update nowait. Это оператор даст вам возможность проверить, не изменились ли данные с момента прочтения и заблокировать строку.

А еще есть такая нехорошая вещь как взаимные блокировки.

Возникают они тогда, когда два сеанса удерживают ресурсы необходимые другому сеансу. Пример. Пусть есть две таблицы по одной записи в каждой. Сеанс1 блокирует таблицу А, сеанс 2 блокирует таблицу Б. Затем сеанс 2 хочет изменить таблицу А, но окажется заблокированным, так как эту таблицу удерживает сеанс1. Сеанс 1 решает, что нужно изменить таблицу Б, то так же оказывается заблокированным, потому что эту таблицу удерживает заблокированный сеанс 2. Вот такая неприятность вышла.

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

 

Новый комментарий

Я не спамер: введите суму 1+1



 

От авторов блога

О Блоге - прочитай перед началом.

Задать вопрос и получить ответ - уже решено 94 вопросов

Глоссарий - список терминов и сокращений


 
 

Бизнес форум

Последние темы:

Спутниковое тв
21 января, 3 ответа