Блокировка – процедура, используемая для управления параллельным доступом к данным. Когда некоторая транзакция получает доступ к базе данных, механизм блокировки позволяет (с целью исключения получения некорректных результатов) отклонить попытки получения доступа к этим же данным со стороны других транзакций.
Именно методы блокировки чаще всего используются на практике для обеспечения упорядоченности параллельно выполняемых транзакций. Существует несколько различных вариантов этого механизма, однако все они построены на одном и том же фундаментальном принципе: транзакция должна потребовать блокировку для чтения(разделяемую) или для записи(эксклюзивную) некоторого элемента данных перед тем, как она сможет выполнить в базе данных соответствующую операцию чтения или записи. Установленный блокпрепятствует модификации элемента данных другими транзакциями или даже считыванию его, если этот блок был установлен для записи. Блокировка может быть выполнена для элементов самого различного размера – начиная с базы данных в целом и заканчивая отдельным полем конкретной записи. Размер блокируемого элемента задается уровнем детализацииустанавливаемого блока.
Блокировка для чтения. Если транзакция установила блокировку элемента данных для чтения, она сможет считать его, но не сможет выполнить обновление.
Блокировка для записи. Если транзакция установила блокировку элемента данных для записи, она может как читать, так и обновлять этот элемент.
Поскольку операция чтения не может служить причиной конфликта, допускается устанавливать блокировку для чтения одного и того же элемента одновременно со стороны сразу нескольких транзакций. В то же время блокировка элемента для записи предоставляет транзакции эксклюзивное право доступа к нему. Следовательно, до тех пор пока транзакция будет удерживать некоторый элемент заблокированным для записи, никакая другая транзакция не сможет ни считать, ни обновить его. Для обеспечения упорядоченности следует использовать дополнительный протокол, определяющий моменты установки и снятия блокировки для каждой из транзакций. Самым известным из таких протоколов является метод двухфазной блокировки.
Двухфазная блокировка– это выполнение транзакции по протоколу, при котором все операции блокирования предшествуют первой операции разблокирования.
В соответствии с основным правилом этого протокола, каждая транзакция может быть разделена на две фазы: фазу нарастания,в которой выполняются все необходимые блокировки и не освобождается ни одного из элементов данных, и фазу сжатия,в которой освобождаются все выполненные ранее блокировки и не может быть затребовано ни одной новой. Нет никакой необходимости в том, чтобы все требуемые блокировки были установлены одновременно. Как правило, транзакция устанавливает некоторые блокировки, выполняет определенную обработку, после чего может затребовать установку дополнительных необходимых ей блокировок. Однако она не может освободить ни одного из блоков, пока не достигнет той стадии, на которой ей уже не потребуется установка новых блокировок.
Есть одна проблема, связанная с двухфазной блокировкой, которая может иметь место при любых схемах освобождения заблокированных элементов. Эта проблема носит название взаимной блокировки и является следствием того факта, что любая транзакция может быть переведена в состояние ожидания освобождения требуемого ей элемента данных. Если две транзакции будут ожидать освобождения элементов, заблокированных другой транзакцией из этой же пары, то возникнет состояние взаимной блокировки. Для исключения самоблокировок может использоваться система приоритетов, в которой приоритет транзакции тем выше, чем дольше она находится в состоянии ожидания. Альтернативным вариантом является использование для ожидающих транзакций очереди, построенной по схеме "первым пришел, первым обслуживается". Однако чаще всего прибегают к самому простому варианту: выбирают в качестве жертвы одну из транзакций и просто ее откатывают. Эти действия несомненно могут ощутимо сказаться на эффективности работы системы.
Предупреждение взаимных блокировок.Один из возможных подходов предупреждения взаимных блокировок состоит в установлении порядка выполнения транзакций на основе использования временных отметок, о чем речь пойдет ниже в этой же главе. Были предложены два возможных алгоритма. Первый алгоритм, получивший название “ожидание-отмена”, требует, чтобы более старые транзакции ожидали завершения более новых. В противном случае транзакция отменяется и перезапускается с той же самой временной отметкой. Однако рано или поздно она станет самой старой из активных транзакций и уже не будет отменена. Второй алгоритм, “отмена-ожидание” использует диаметрально противоположный подход: только более новые могут ожидать завершения более старой транзакции. Если более старая транзакция потребует выполнения блокировки элемента данных, уже заблокированного более новой транзакцией, последняя будет отменена. Иногда для предупреждения тупиков система строит граф выполнения транзакций и пытается заранее определить тупиковые ситуации.