- •Глава 13. Семантическое моделирование
- •Часть III Проектирование базы данных
- •Часть IV
- •14.1. Введение
- •14.2. Транзакции
- •14.3. Восстановление транзакции
- •14.4. Восстановление системы
- •14.5. Восстановление носителей
- •14.6. Двухфазная фиксация
- •14.7. Поддержка языка sql
- •14.8. Резюме
- •15.1. Введение
- •15.2. Три проблемы параллельности
- •15.3. Блокировка
- •15.4. Устранение трех проблем параллельности
- •15.5. Взаимная блокировка
- •15.6. Упорядочиваемость
- •15.7. Уровни изоляции
- •15.8. Блокировка намерения
- •15.9. Средства языка sql
- •15.10. Резюме
- •Часть V
- •16.1. Введение
- •16.2. Избирательная схема управления доступом
- •16.3. Мандатная схема управления доступом
- •16.4. Статистические базы данных
- •16.5. Шифрование данных
- •16.6. Средства языка sql
- •16.7. Резюме
- •17.1. Введение
- •17.2. Пример выполнения оптимизации
- •17.3. Оптимизация запросов
- •17.4. Преобразование выражений
- •17.5. Статистические показатели базы данных
- •17.6. Стратегия по принципу "разделяй и властвуй"
- •17.7. Реализация реляционных операторов
- •17.8. Резюме
- •18.1. Введение
- •18.2. Обзор концепции трехзначной логики
- •18.3. Некоторые следствия изложенной схемы
- •18.4. Отсутствующие значения и ключи
- •18.5. Внешнее соединение
- •18.6. Специальные значения
- •18.7. Поддержка неопределенных значений в языке sql
- •18.8. Резюме
- •Глава 19
- •19.1. Введение
- •19.2. Иерархия типов
- •19.3. Полиморфизм и заменимость
- •19.4. Переменные и операция присвоения
- •19.5. Специализация по ограничениям
- •19.6. Операции сравнения
- •19.7. Операторы, версии и сигнатуры
- •19.8. Является ли окружность эллипсом
- •19.9. Пересмотр специализации ограничением
- •19.10. Резюме
- •20.1. Введение
- •20.2. Предварительные сведения
- •20.3. Двенадцать основных целей
- •1. Локальная независимость
- •2. Отсутствие опоры на центральный узел
- •3. Непрерывное функционирование
- •4. Независимость от расположения
- •5. Независимость от фрагментации
- •6. Независимость от репликации
- •7. Обработка распределенных запросов
- •8. Управление распределенными транзакциями
- •9. Аппаратная независимость
- •10. Независимость от операционной системы
- •11. Независимость от сети
- •12. Независимость от типа субд
- •20.4. Проблемы распределенных систем
- •Транзакция т1х
- •20.5. Системы "клиент/сервер"
- •20.6. Независимость от субд
14.2. Транзакции
Как уже указывалось в разделе 14.1, мы начнем с изучения фундаментального поня- тия транзакции. Транзакция — это логическая единица работы. Рассмотрим следую- щий пример. Предположим сначала, что переменная-отношение Р (переменная- отношение деталей) включает дополнительный атрибут TOTQTY, представляющий собой общий объем поставок для каждой детали. Другими словами, предполагается, что значе- ние атрибута TOTQTY для любой конкретной детали равно сумме всех значений атрибута QTY для всех поставок данной детали (в терминах главы 8 это ограничение базы данных). На рис. 14.1 показан псевдокод процедуры вставки в базу данных сведений о новой по- ставке со значением 1000 для поставщика 'S5' и детали 'Р1' (команда INSERT добавляет сведения о новой поставке в отношение SP, а команда UPDATE обновляет значение атри- бута TOTQTY для детали ' РГ).
В приведенном примере предполагается, что речь идет об одиночной, атомарной операции. На самом деле добавление сведений о новой поставке — это выполнение двух обновлений в базе данных: операции INSERT и операции UPDATE. Более того, в базе дан- ных между этими двумя обновлениями временно нарушается требование, что значение атрибута TOTQTY для детали 'Р1' равно сумме всех значений атрибутов QTY для этой де- тали. Таким образом, логическая единица работы (т.е. транзакция) вовсе необязательно является простой одиночной операцией системы баз данных; чаще всего она представля- ет собой последовательность из нескольких таких операций. В общем случае выполне- ние этой последовательности переводит базу данных из одного непротиворечивого со- стояния в другое, причем в промежуточных точках выполнения база данных может на- ходиться в противоречивом состоянии.
Из этого следует, что не допустимо, чтобы одно из обновлений было выполнено, а другое нет, так как в этой ситуации база данных останется в противоречивом состоянии. В идеальном случае необходимо иметь абсолютную гарантию, что всегда будут выпол- няться оба обновления. К сожалению, подобную гарантию дать нельзя, поскольку нельзя исключить вероятность того, что может случиться что-то непредвиденное, причем в са- мый неподходящий момент. Например, между операциями INSERT и UPDATE может про- изойти сбой системы или же во время выполнения второй операции может возникнуть арифметическое переполнение и т.п. Однако система, поддерживающая обработку транзакций, гарантирует максимум из того, что можно гарантировать, а именно — что если во время выполнения неких обновлений произойдет ошибка (по любой причине), то все эти обновления будут отменены. Таким образом, транзакция или полностью выпол- няется, или полностью отменяется (как будто она вообще не выполнялась), т.е. выполне- ние неатомарной последовательности операций с точки зрения внешнего наблюдателя будет выглядеть так же, как выполнение атомарной операции.
Системный компонент, обеспечивающий атомарность (или ее подобие), называется менеджером транзакций или диспетчером обработки транзакций (transaction processing monitor— TP-monitor), а ключевыми элементами в его выполнении служат операторы COMMIT и ROLLBACK.
Оператор COMMIT (зафиксировать) сигнализирует об успешном окончании транзак- ции. Он сообщает менеджеру транзакций, что логическая единица работы успеш- но завершена, база данных вновь находится (или будет находиться) в непротиво- речивом состоянии, а все обновления, выполненные данной логической единицей работы, теперь могут быть "зафиксированы", т.е. сделаны постоянными.
Оператор ROLLBACK (откатить) сигнализирует о неудачном окончании транзакции. Он сообщает менеджеру транзакций, что произошла какая-то ошибка, база данных находится в противоречивом состоянии и следует выполнить "откат" всех проведен- ных при выполнении этой транзакции обновлений, т.е. они должны быть отменены.
Таким образом, в приведенном примере оператор COMMIT должен выполняться, если оба обновления прошли успешно, после чего выполненные в базе данных изменения станут по- стоянными. Если что-то не так, если обновление было прервано каким-либо условием ошибки, то выполняется оператор ROLLBACK и любые внесенные изменения отменяются.
Замечание. Даже если в последнем случае попытаться выполнить оператор COMMIT, то система, в принципе, все равно должна проверить соблюдение существующих ограниче- ний целостности, обнаружить противоречивость возникшего состояния базы данных и
принудительно выполнить откат. Однако следует быть реалистами и понимать, что сис- тема не всегда может знать обо всех уместных в каждой конкретной ситуации ограниче- ниях, а потому выполнение оператора ROLLBACK по требованию пользователя следует считать необходимым. На момент написания этой книги коммерческие СУБД обладали лишь ограниченными возможностями проверки ограничений целостности в процессе фиксации транзакций.
Кстати, следует отметить, что реальные приложения могут не только модифициро- вать базу данных (или пытаться это сделать), но также отсылать пользователю некото- рые сообщения о том, что произошло. В нашем примере можно отослать пользователю сообщение "Сведения о поставке введены" после выполнения операции COMMIT и сооб- щение "Ошибка — сведения о поставке не введены" в противном случае. Выдача сооб- щений, в свою очередь, имеет дополнительное значение для восстановления. Более под- робно эти вопросы обсуждаются в [14.12].
Замечание. Читателя может удивить тот факт, что обновление можно отменить. Дело в том, что система поддерживает файл или журнал регистрации на ленте либо чаще всего на диске, где записываются детальные сведения обо всех выполненных операциях обновления и, в частности, новое и старое значения модифицированного объекта. Таким образом, при необ- ходимости отмены некоторого обновления система может использовать соответствующий журнал регистрации для возвращения объекта в первоначальное состояние.
(На самом деле это слишком упрощенное объяснение. На практике журнал регистра- ции состоит из двух частей: активной (или оперативной) и архивной (или автономной). Оперативная часть используется во время нормальной работы системы для записи под- робных сведений об осуществляемых обновлениях и обычно размещается на диске. По- сле того как файл оперативной части заполняется, его содержимое перемещается в авто- номную часть, которая обычно размещается на магнитной ленте, поскольку эта часть всегда обрабатывается последовательно.)
Еще один важный момент. Система должна гарантировать, что индивидуальные опе- раторы сами по себе атомарны (т.е. выполняются полностью или не выполняются совсем). Это особенно важно для реляционных систем, в которых операторы многоуров- невые и обычно оперируют множеством кортежей одновременно. Выполнение таких операторов ни в коем случае не должно прерываться до завершения операции, в резуль- тате чего система может остаться в противоречивом состоянии (например, если обнов- лена только часть требуемых кортежей). Другими словами, если произошла ошибка во время выполнения подобного оператора, база данных должна остаться полностью неиз- мененной. Более того, как объясняется в главах 8 и 9, это должно быть справедливо даже в том случае, когда действия оператора являются причиной выполнения дополнительных фоновых операций, например каскадного удаления внешних ключей.