Схемы блокировок в базах данных. Блокирование и разблокирование

Также в некоторых СУБД можно устанавливать интервал времени time out – превышение лимита времени. При введении такого интервала инструкция SQL заканчивается неуспешно и возвращает код ошибки, если она не смогла установить требуемую блокировку в течение определенного промежутка времени.

Администратор БД может вручную устанавливать типы, уровни блокировок и время time out в зависимости от прикладной программы.

Режимы блокировки для конкретного приложения (программы) можно также устанавливать программно с помощью соответствующих методов объекта Recordset языка VBA. При этом в конкретном случае будут уже действовать установки программы, а не общие установки окна Параметры . Этот вариант обеспечивает более гибкие возможности блокировки, но в данном курсе он только упоминается, подробно не рассматривается.

Методы управления блокировками в MS Access

Microsoft Access является многопользовательской СУБД. В ней имеются определенные механизмы блокировок для поддержания совместного доступа к данным и разрешения конфликтов при доступе к данным.

Существует три типа блокировки записей в базе данных Access.

· Блокировка отсутствует . Значок этого режима. Если два пользователя одновременно вносили изменения в запись, то тот, кто сохраняет изменения первым, может это сделать. Когда второй пользователь попытается сохранить свои изменения, то появляется диалоговое окно « Конфликт записи», в котором ему предлагается или сохранить свою запись, уничтожив изменения первого пользователя, или скопировать свои изменения в буфер, или отменить свои изменения. Этот вариант называют оптимистической блокировкой, поскольку она основывается на предположении, что при редактировании конфликта с его альтернативными исходами не произойдет.

· Блокировка изменяемой записи .
Access блокирует изменяемую в данный момент запись, не позволяя изменять ее другим пользователям. Заблокированными могут оказаться также записи, расположенные рядом на диске. Если другой пользователь попытается изменить заблокированную запись, у не

го появится маркер заблокированной записи.

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

· Блокировка всех записей .
Microsoft Access блокирует все записи формы или объекта в режиме Таблицы, поэтому другие пользователи не могут изменить или заблокировать записи. Этот параметр накладывает жесткие ограничения и явно снижает производительность.

Чтобы установить параметры блокировки записей необходимо:

1. Выбрать команду Office → Параметры Access . Появится диалоговое окно Параметры Access.

2. Раскрыть вкладку Дополнительно, раздел Дополнительно.

В группе Режим открытия по умолчанию можно выбрать режим Общий доступ или режим Монопольный доступ - открытие существующей базы данных для монопольного использования одним пользователем.

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

Существует возможность выбора одного из трех уровней блокировки:

  • Отсутствует.
  • Блокировка изменяемой записей. Блокируется только редактируемая запись.
  • Блокировка всех записей. Блокируются все записи таблицы, отображаемые в форме или таблице.

Период обновления (с) Число секунд, после которых Microsoft Access автоматически обновит записи в режиме таблицы или формы.

Число повторов обновления Количество попыток, когда Microsoft Access пытается сохранить измененную запись, заблокированную другим пользователем. Возможные значения от 0 до 10. Значение по умолчанию: 2.

Установленные параметры начнет действовать, когда база данных будет открыта заново с помощью команды Файл, Открыть .

Если нужна блокировка на уровне записей при открытии БД, то нужно установить флажок Открытие баз данных с использованием блокировки на уровне записей. Если необходима блокировка по умолчанию на уровне страниц, то этот флажок нужно сбросить.

Кроме этих вариантов блокировки записей имеется ещё один метод, заключающийся в установки нужного режима работы с данными в форме. Для этого нужно открыть форму в режиме конструктора и на вкладке Данные Окна свойств для свойства Блокировка записей выбрать одну из опций блокировки: отсутствует, всех записей, изменяемой записи .

Контрольные вопросы и упражнения

  1. Сформулируйте определение транзакции. Приведите примеры транзакций.
  2. Как выполняются транзакции в языке SQL?
  3. Назовите и поясните смысл параметров транзакций? Как установить значения параметров?
  4. Охарактеризуйте каждый из уровней изоляции транзакций:
    READ INCOMMITED, READ COMMITED, REPEATABLE READ, SERIAIZABLE.
  5. Что такое журнал транзакций? Какие поля он содержит? Для чего и как он используется?
  6. Для чего в СУБД используются блокировки данных при обработке транзакций?
  7. Назовите и охарактеризуйте используемые уровни блокировок?
  8. Как устанавливаются режимы блокировки данных в СУБД MS ACCESS?

При работе с объектными данными (справочники, документы, планы счетов и т.д.) система «1С:Предприятие» обеспечивает два вида объектных блокировок: пессимистическую и оптимистическую. Они позволяют выполнять целостные изменения объектов при одновременной работе нескольких пользователей.

Объектная пессимистическая блокировка

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

Рассмотрим пример.
Войдем в учебную информационную базу под пользователем «Васильев В.В.», откроем форму документа «Поступление товаров 00000000001 от 01.06.2016» и внесем изменения в поле комментарий (рис. 1.3).

Не сохраняя документ войдем в информационную базу под пользователем «Иванов И.И.», откроем тот же документ и попробуем внести изменения в любом реквизите документа. Система не даст нам внести изменения и выдаст сообщение об ошибке (рис. 1.4).

Отсюда следует, что пессимистическая блокировка гарантирует, что пользователь, начав изменять данные объекта, сможет записать эти изменения в информационную базу.

Разработчик используя средства встроенного языка может задействовать пессимистическую блокировку. Используя метод «Заблокировать()» происходит установка пессимистической объектной блокировки, а для снятия используется метод «Разблокировать()».


Давайте рассмотрим другой пример. Под пользователем «Васильев В.В.» в разделе «Нормативно-справочная информация» откроем элемент справочника «Склады» с наименованием «Склад №1» и внесем изменения в наименование (рис. 1.5).


Не сохраняя переключимся в окно информационной базы, который был запущен под пользователем «Иванов В.В.», в разделе «Нормативно-справочная информация» откроем обработку «Удаление объекта». Выберем в качестве удаляемого объекта выберем элемент справочника «Склады» с наименованием «Склад №1» и нажмем «Удалить объект» (рис. 1.6).

В результате система позволит удалить данный элемент справочника и система не выдаст сообщение об ошибке. Дело в том, что операция блокирования не препятствует операции изменения или удаления объекта в базе данных.

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

Есть два способа проверки:

  1. Метод «Заблокирован()» используется для проверки блокировки объекта базы данных текущим сеансом. Данный метод не предоставляет возможность проверки заблокирован ли объект вообще.
  2. Для проверки заблокирован объект базы данных вообще используется метод «Заблокировать()». Попытка блокировки заблокированного объекта вызывает исключение, которое может быть обработано конструкцией «Попытка…..Исключение…..КонецПопытки».

Пессимистическая блокировка в управляемых формах

При работе с управляемыми формами методы «Заблокировать()», «Разблокировать()» и «Заблокирован()» могут не подойти из-за специфики работы управляемого приложения.

Дело в том, что данные методы используются для объектов базы данных. Объект базы данных существует только на сервере. Получается разработчику придется выполнить серверный вызов, получить объект базы данных путем преобразования основного реквизита формы с помощью метода формы «РеквизитФормыВЗначение». Далее вызывается один из методов объекта «Заблокировать()», «Разблокировать()» или «Заблокирован()». Но данный способ блокировки будет бесполезен, если задача стоит, чтобы объект был заблокирован пока открыта форма, так как полученный объект будет жить до конца серверного вызова.

Для работы с блокировками из управляемой формы необходимо использовать методы: «ЗаблокироватьДанныеФормыДляРедактирования()» и «РазблокироватьДанныеФормыДляРедактирования()». Данные методы используются для блокировки или разблокировки данных основного реквизита формы.

Рассмотрим пример. В разделе «Нормативно-справочная информация» откроем любой элемент справочника «Номенклатура» под пользователем «Васильев В.В.», внесем изменения в наименование и не сохраняя под пользователем «Иванов И.И.» отроем тот же элемент справочника. При попытки внесения изменений система выдаст сообщение об ошибке.


Далее в форме элемента справочника под пользователем «Васильев В.В.» нажмем на кнопку «Разблокировать» (рис. 1.7) и попробуем снова внести изменения в данный элемент справочника под пользователем «Иванов И.И.». В данном случае система даст внести изменения и записать элемент справочника.


Для отключения пессимистической блокировки в управляемых формах в свойстве основного реквизита надо снять флаг «Сохраняемые данные». Данный флаг определяет будет ли при интерактивном редактировании блокироваться данные основного реквизита, или нет рис(1.8).

Объектная оптимистическая блокировка

Оптимистическая блокировка представляет собой проверку, которая выполняется перед записью объекта в базу данных. У объекта есть свойство «ВерсияДанных», которая вместе с объектом считывается из базы данных. Оптимистическая блокировка производит перед записью производит сравнение значения свойства «ВерсияДанных» объекта, который находится в оперативной памяти с значением свойства «ВерсияДанных» объекта находящийся в базе данных. Если значения свойства «ВерсияДанных» у объектов отличается, то оптимистическая блокировка запрещает запись объекта в базу данных и выдает сообщение об ошибке.

Рассмотрим пример.

В разделе «Нормативно-справочная информация» откроем любой элемент справочника «Номенклатура» под пользователем «Васильев В.В.», далее не закрывая форму элемента под пользователем «Иванов И.И.» в разделе «Нормативно-справочная информация» откроем обработку «Изменить объект».

В обработке выберем ту же номенклатуру и нажмем кнопку «Изменить объект». Данная команда добавит в конце наименования «!!!» (рис. 1.9).

После изменения попробуем записать открытый элемент справочника номенклатуры под пользователем «Васильев В.В.». Система выдаст предупреждение о том, что данные объекты были изменены или удалены и не даст записать данный объект (рис. 1.10).

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

для него метод экземпляра destroy. Семантическое различие трудноуловимо, но становится понятным, когда задаются обратные вызовы before_destroy или возникают зависимые ассоциации, то есть дочерние объекты, которых нужно автоматически удалить вместе с родителем.

Блокировка базы данных

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

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

конкурентностью . Спросите себя, какиеколлизии илигонки (race conditions) могут иметь место, если два пользователя попытаются обновить модель в один и тот же момент?

К учету конкурентности в приложениях, работающих с базой данных, есть несколько подходов. В ActiveRecord встроена поддержка двух из них: оптимистической ипессимистической блокировки. Есть и дру-

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

Оптимистическая блокировка

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

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

Если вы контролируете схему базы данных, то реализовать оптимистическую блокировку совсем просто. Достаточно добавить в таблицу целочисленную колонку с именем lock_version и значением по умолчанию 0:

Блокировка базы данных

AddLockVersionToTimesheets < ActiveRecord::Migration

add_column:timesheets, :lock_version, :integer, :default => 0

remove_column:timesheets, :lock_version end

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

ключение ActiveRecord::StaleObjectError.

Для иллюстрации оптимистической блокировки напишем простой автономный тест:

class TimesheetTest < Test::Unit::TestCase

fixtures:timesheets, :users

def test_optimistic_locking_behavior first_instance = Timesheet.find(1) second_instance = Timesheet.find(1)

first_instance.approver = users(:approver) second_instance.approver = users(:approver2)

assert first_instance.save, "Успешно сохранен первый экземпляр"

assert_raises ActiveRecord::StaleObjectError do second_instance.save

Тест проходит, потому что при вызове save для второго экземпляра мы ожидаем исключения ActiveRecord::StaleObjectError. Отметим,

что метод save (без восклицательного знака) возвращает false и не возбуждает исключений, если сохранение не выполнено из-за ошибки контроля данных . Другие проблемы, например блокировка записи, могут приводить к исключению. Если вы хотите, чтобы колонка, содержащая номер версии, называлась неlock_version , а как-то иначе, измените эту настройку с помощью метода set_locking_column. Чтобы это изменение действовало глобально, добавьте в файлenvironment.rb такую строку:

ActiveRecord::Base.set_locking_column "alternate_lock_version"

Как и другие настройки ActiveRecord, эту можно задать на уровне модели, если включить в класс модели такое объявление:

class Timesheet < ActiveRecord::Base set_locking_column "alternate_lock_version"

Обработка исключения StaleObjectError

Добавив оптимистическую блокировку, вы, конечно, не захотите остановиться на этом, поскольку иначе пользователь, оказавшийся проигравшей стороной в разрешении коллизии, просто увидит на экране сообщение об ошибке. Надо постараться обработать исключение StaleObjectError с наименьшими потерями.

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

def update begin

@timesheet = Timesheet.find(params[:id]) @timesheet.update_attributes(params[:timesheet])

# куда-нибудь переадресовать rescue ActiveRecord::StaleObjectError

flash[:error] = "Табель был модифицирован, пока вы его редактировали." redirect_to:action => "edit", :id => @timesheet

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

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

Пессимистическая блокировка

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