- •Часть IV
- •Глава 13 Восстановление
- •13.1. Введение
- •13.2. Транзакции
- •13.3. Восстановление транзакции
- •13.4. Восстановление системы
- •13.5. Восстановление носителей
- •13.6. Двухфазная фиксация
- •13.7. Поддержка языка sql
- •13.8. Резюме
- •Глава 14 Параллелизм
- •14.1. Введение
- •14.2. Три проблемы параллелизма
- •14.3. Блокировка
- •14.4. Решение проблем параллелизма
- •14.5. Тупиковая ситуация
- •14.6. Способность к упорядочению
- •14.7. Уровни изоляции
- •14.8. Преднамеренная блокировка
- •IX s
- •14.9. Поддержка блокировок в sql
- •14.10. Резюме
- •14.13. Papadimitriou с. The Theory of Database Concurrency Control.— Rockville, Md.: Computer Science Press, 1986.
- •Глава 15 Безопасность
- •15.1. Введение
- •15.2. Общие соображения
- •15.3. Избирательное управление доступом
- •15.4. Модификация запроса
- •15.5. Обязательное управление доступом
- •15.6. Шифрование данных
- •Стандарт шифрования данных
- •15.7. Поддержка мер обеспечения безопасности в языке sql
- •15.8. Резюме
13.2. Транзакции
Как уже указывалось, начнем с фундаментального изучения транзакции. Транзакция — это логическая единица работы. Рассмотрим пример. Предположим сначала, что отношение Р (отношение деталей) включает дополнительный атрибут TOTQTY, представляющий собой общий объем поставок для каждой детали. Значение TOTQTY для любой определенной детали предполагается равным сумме всех значений QTY для всех поставок данной детали. На рис. 13.1 показано добавление в базу данных новой поставки со значением 1000 для поставщика S5 и детали PI (insert добавляет новую поставку к отношению SP, a update обновляет значение TOTQTY для детали Р1).
В приведенном примере предполагается, что речь идет об одиночной, атомарной операции. На самом деле добавление новой поставки — это выполнение двух обновлений в базе данных (под обновлениями здесь, конечно, понимаются операции insert, delete, а также сами по себе операции update). Более того, в базе данных между этими двумя обновлениями временно нарушается требование, что значение TOTQTY для детали Р1 равно сумме всех значений QTY для этой детали. Таким образом, логическая единица работы (т.е. транзакция) — не просто одиночная операция системы баз данных, а скорее согласование нескольких таких операций. В общем, это преобразование одного согласованного состояния базы данных в другое, причем в промежуточных точках база данных находится в несогласованном состоянии.
BEGIN TRANSACTION ;
INSERT ( { S#:'S5', Р#:'Р1', QTY:1000 } ) INTO SP ;
IF возникла ошибка THEN GO TO UNDO ;
UPDATE P WHERE P# = 'Р1' TOTQTY := TOTQTY + 1000 ;
IF возникла ошибка THEN GO TO UNDO ;
COMMIT TRANSACTION ;
GO TO FINISH ;
UNDO :
ROLLBACK TRANSACTION ;
FINISH :
RETURN ;
Рис. 13.1. Пример транзакции (псевдокод)
Из этого следует, что не допустимо, чтобы одно из обновлений было выполнено, а другое нет, так как база данных останется в несогласованном состоянии. В идеальном случае должны быть выполнены оба обновления. Однако нельзя обеспечить стопроцентную гарантию, что так и будет. Не исключена вероятность того, что дела пойдут плохо. Например, система может быть разрушена между двумя обновлениями, или же на втором обновлении произойдет арифметическое переполнение и т.п. Однако система, поддерживающая процесс транзакции, обеспечивает гарантию, что если во время выполнения неких обновлений произошла ошибка (по любой причине), то все эти обновления будут аннулированы. Таким образом, транзакция или выполняется полностью, или полностью отменяется (как будто она вообще не выполнялась).
Системный компонент, обеспечивающий атомарность (или ее подобие), называется администратором транзакций (или диспетчером транзакций), а ключами к его выполнению служат операторы commit transaction и rollback transaction.
• Оператор commit transaction (для краткости commit) сигнализирует об успешном окончании транзакции. Он сообщает администратору транзакций, что логическая единица работы завершена успешно, база данных вновь находится (или будет находиться) в согласованном состоянии, а все обновления, выполненные логической единицей работы, теперь могут быть зафиксированы, т.е. стать постоянными.
• Оператор rollback transaction (для краткости rollback) сигнализирует о неудачном окончании транзакции. Он сообщает администратору транзакций, что произошла какая-то ошибка, база данных находится в несогласованном состоянии и все обновления могут быть отменены, т.е. аннулированы.
Следовательно, commit выполняется, если оба обновления прошли успешно, изменения в базе данных выполнены и стали постоянными. Если что-то не так, если обновление прервано каким-либо условием ошибки, то выполняется rollback и любые изменения отменяются.
Обратите внимание, что при этом можно не только модифицировать базу данных (или попытаться это сделать), но также и выдать пользователю некоторое сообщение о том, что произошло. Например, можно выдать сообщение "Поставка добавлена", если выполнена операцияcommit, или "Ошибка — поставка не добавлена", если операция не выполнена. Выдача сообщений имеет дополнительное значение для восстановления. Для более подробного обсуждения вопросов по этой теме можете обратиться к [13.11].
Читателя может удивить отмена обновления. Но дело в том, что система поддерживает файл регистрации, или журнал, на ленте или (обычно) на диске, где записываются детали всех операций обновления, в частности новое и старое значения модифицированного объекта. Таким образом, при необходимости отмены некоторого обновления система может использовать соответствующий файл регистрации для возвращения объекта в первоначальное состояние.
(На самом деле это слишком упрощенное объяснение. На практике файл регистрации состоит из двух частей: активной (или интерактивной) и архивной (или автономной). Интерактивная часть используется во время нормальной системной операции по записи деталей осуществляемых обновлений и обычно содержится на диске. После того как интерактивная часть заполнена, ее содержимое перемещается в автономную часть, которая обычно находится на ленте, поскольку обрабатывается последовательно.)
Еще один важный момент. Система должна гарантировать, что индивидуальные операторы сами по себе атомарны (т.е. выполняются полностью или не выполняются совсем). Это особенно важно для реляционных систем, в которых операторы многоуровневые и обычно оперируют множеством кортежей одновременно; такой оператор просто не может быть нарушен посреди операции и привести систему в несогласованное состояние (например, если выполнена только часть необходимых действий). Другими словами, если произошла ошибка во время работы такого оператора, база данных должна остаться полностью неизмененной. Более того, это должно быть справедливо даже в том случае, когда действия оператора являются причиной дополнительной, например каскадной, операции.