Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Информатика и ВТ Брукшир.doc
Скачиваний:
0
Добавлен:
01.07.2025
Размер:
5.07 Mб
Скачать

9.5.3Блокировка

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

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

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

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

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