Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
db-shpora.doc
Скачиваний:
14
Добавлен:
08.11.2018
Размер:
1.44 Mб
Скачать
  1. Блокировка ресурсов: взаимная блокировка

Решая одну проблему, блокировка способна вызвать другую. Посмотрим, что может произойти, когда два пользователя хотят заказать две единицы товара. Предполо­жим, что пользователь А хочет заказать бумагу, и если он сможет получить ее, то хочет заказать и карандаши. Теперь предположим, что пользователь В хочет зака­зать карандаши, а если удастся достать их, то он закажет еще и бумагу. Возмож­ный порядок обработки показан на рис. 6.

На этом рисунке пользователи А и В оказываются в ситуации, которая носит название взаимной блокировки (deadlock), или «смертельного объятия» (deadly embrace). Каждый из них ожидает освобождения ресурса, заблокированного дру­гим пользователем. Есть два распространенных способа решения этой проблемы: не допускать возникновения взаимных блокировок либо позволять им возникать, а затем распутывать их.

Предотвратить возникновение взаимной блокировки можно несколькими спо­собами. Первый из них – заставлять пользователей блокировать все требуемые ресурсы сразу. Если бы, например, пользователь А на рисунке с самого начала заблокировал и карандаши, и бумагу, взаимная блокировка не возникла бы. Второй способ предотвратить взаимную блокировку – потребовать от всех прикладных программ блокировать ресурсы в одном и том же порядке. Даже если не все при­ложения будут налагать блокировки таким образом, вероятность возникновения взаимной блокировки снизится хотя бы для тех приложений, которые используют данную стратегию. Эту философию можно распространить на организационные стандарты программирования следующим образом: «При обработке строк таб­лиц в связи родитель-потомок всегда блокируй сначала родителя, затем потом­ка». Это, по крайней мере, снизит вероятность взаимной блокировки, а может и вовсе исключить ее.

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

  1. Блокировка ресурсов: оптимистическая и пессимистическая блокировки

Блокировки могут налагаться двумя основными стилями. При оптимистической блокировке (optimistic locking) делается предположение, что конфликта не про­изойдет. Данные считываются, транзакция обрабатывается, производятся обнов­ления, а после этого проверяется, не возник ли конфликт. Если нет, транзакция завершается. Если да, транзакция повторяется до тех пор, пока не сможет успешно завершиться. При пессимистической блокировке (pessimistic locking) предполага­ется, что конфликт обязательно произойдет. Сначала налагаются блокировки, затем обрабатывается транзакция, а после этого блокировки снимаются.Листинги 1,2 и 3 демонстрируют оба стиля наложения блокировок для транзакции, которая уменьшает количество карандашей в таблице ТОВАР на пять штук. Сначала дан­ные считываются, и текущее количество карандашей сохраняется в переменной СтароеКоличество. Затем обрабатывается транзакция, и в предположении, что все прошло успешно, налагается блокировка на таблицу ТОВАР. Эта блокировка мо­жет затрагивать только строку карандашей, а может быть, глубина детализации будет и меньшей. В любом случае, выполняется SQL-оператор, обновляющий строку карандашей, с условием WHERE Количество = СтароеКоличество. Если ника­кая другая транзакция не изменила атрибут Количество в строке карандашей, то­гда результат оператора UPDATE будет успешным. Если какая-то другая транзак­ция изменила значения атрибута Количество в строке карандашей, выполнение оператора UPDATE будет неудачным, и транзакцию придется повторить.

Листинг 1. Оптимистическая блокировка

SELECT ТОВАР.Название, ТОВАР.Количество FROM ТОВАР

WHERE ТОВАР.Название ='Карандаш' СтароеКоличество = ТОВАР.Количество

Set НовоеКоличество = ТОВАР.Количество - 5

{обработка транзакции - если НовоеКоличество < 0, то генерируется исключение, и т. д. Если все в порядке:}

LOCK ТОВАР UPDATE ТОВАР SET ТОВАР.Количество = НовоеКоличество

WHERE ТОВАР.Название = 'Карандаш'

AND ТОВАР.Количество = СтароеКоличество

UNLOCK ТОВАР

{проверяем, было ли обновление успешным; если нет, повторяем транзакцию}

В листинге Здесь еще до начала работы на таблицу ТОВАР налагается блокировка (с некоторой глубиной детализации). Затем счи­тываются значения, обрабатывается транзакция, выполняется оператор UPDATE, и таблица ТОВАР разблокируется.

Преимущество оптимистической блокировки состоит в том, что она налагается только после обработки транзакции. Таким образом, блокировка удерживается в течение более короткого времени, чем при пессимистической стратегии. Если транзакция является сложной или клиент — медлительным (например, имеются задержки при передаче, клиент занят другой работой, пользователь уходит попить кофе или выключает компьютер, не выйдя из браузера), то блокировка будет удерживаться в течение значительно меньшего промежутка времени. Это преимущество будет еще более важно, если глубина детализации блокировки ма­ла — скажем, вся таблица ПРОДУКТ.

Листинг 2. Пессимистическая блокировка

LOCK ТОВАР

SELECT ТОВАР.Название, ТОВАР.Количество

FROM ТОВАР

WHERE ТОВАР.Название ='Карандаш'

Set НовоеКоличество = ТОВАР.Количество - 5

{обработка транзакции - если НовоеКоличество < 0, генерируется исключение, и т. д. Если все в порядке:}

UPDATE ТОВАР

SET ТОВАР.Количество = НовоеКоличество

WHERE ТОВАР.Название = 'Карандаш'

UNLOCK ТОВАР

{проверка на успешность обновления не требуется}

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

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]