Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Лекции2011.doc
Скачиваний:
1
Добавлен:
01.05.2025
Размер:
1.86 Mб
Скачать

Проблема строк-призраков

На рис. 6.8 еще раз изображена программа для обработки заказов. На этот раз менеджер по продажам запустил программу генераций отчетов, которая просматривает таблицу orders и печатает список заказов от клиентов Билла Адамса, подсчитывая их итоговую сумму. Тем временем Биллу звонит клиент и размещает дополнительный заказ на $5000. Заказ добавляется в базу данных, и транзакция завершается. Вскоре после этого программа менеджера по продажам снова просматривает таблицу orders, выполняя тот же запрос, что и прежде. На этот раз в таблице имеется дополнительный заказ, а итоговая сумма заказов на $5000 больше, чем сумма заказов в результате первого запроса.

Здесь, как и в предыдущем примере, проблема заключается в несогласованных данных. Состояние базы данных соответствует ситуации в реальной жизни, и целостность данных не нарушена, но один и тот же запрос, выполненный дважды в течение одной транзакции, возвращает два различных результата. В предыдущем примере запрос считывал одну строку, и противоречивость данных была вызвана выполнением оператора update. Выполнение оператора delete могло бы вызвать ту же проблему. В примере, представленном на рис. 6.8, проблема возникла в результате выполнения оператора insert. В первом запросе дополнительной строки не было, и после выполнения второго запроса сложилось такое впечатление, что она появилась из ниоткуда, как призрак. Проблема строк-призраков, как и проблема несогласованных данных, может привести к противоречивым и неправильным расчетам.

Рисунок 6.8 - Проблема строк-призраков

6. Параллельные транзакции

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

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

Таким образом, в реляционной базе данных транзакции играют ключевую роль как при восстановлении после сбоя, так и при параллельной работе нескольких пользователей. Правило, приведенное выше, можно сформулировать иначе с помощью термина "параллельная транзакция": когда две транзакции А и В выполняются параллельно, СУБД гарантирует, что результаты их выполнения будут точно такими же, как и в случае, если: а – сначала выполняется транзакция А, а затем транзакция В; или сначала выполняется транзакция В, а затем транзакция А.

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

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

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

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

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

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

Рисунок 6.9 - Блокировка при одновременном выполнении двух транзакций

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