Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
dbbook(2010.04.15).pdf
Скачиваний:
51
Добавлен:
09.06.2015
Размер:
2.14 Mб
Скачать

3.6.2. Пример декларативной поддержки целостности

Практическое задание. Имеется следующий фрагмент базы данных:

Курсы(КодК, ИмяК) Организации(КодО, ИмяО) Лекторы(КодЛр, Ф, И, О, КодО)

Лекции(КодЛр, КодК, ДатаНач, ДатаКон)

Предполагается, что лектор может участвовать в чтении лекций, не числясь в какой-либо организации из имеющегося списка организаций. Ключи (КодК, КодО и КодЛр) являются суррогатными. Напишите на псевдокоде операторы создания указанных базовых отношений и обоснуйте на содержательном уровне формулировку правил целостности.

Примечание. Для сокращения записи введем целочисленный тип счетчика counter. Значения счетчика генерируются автоматически при вставке кортежей и не допускают обновления. Кроме того, счетчик не может принимать null-значений

Решение. При создании отношения Курсы требуем, чтобы наименование курса (ИмяК) было уникальным и не могло принимать null-значений (можно было бы запретить и пустые значения):

create table Курсы КодК counter, ИмяК char not null primary key(КодК)

candidate key(ИмяК)

Аналогичные ограничения сформулируем и для отношения Организации:

create table Организации КодО counter,

ИмяО char not null primary key(КодО) candidate key(ИмяО)

Так как лектор может не числиться в какой-либо организации, то при создании отношения Лекторы для внешнего ключа КодО null-значения полагаем допустимыми и для операции удаления сведений об организации применяем правило присвоения null-значений (on delete set null):

create table Лекторы КодЛр counter

Ф char not null, И char not null, О char not null, КодО integer null

primary key(КодЛр)

foreign key(КодО) references Организации(КодО) on delete set null

Примечание. Реакцию на обновление значения КодО в родительском отношении определять нет необходимости, так как это значение обновить нельзя

В отношении Лекции внешние ключи КодЛр и КодК являются атрибутами первичного ключа.

Поэтому для них null-значения объявляются недопустимыми. Реакции на обновление их значений в родительских отношениях определять нет необходимости, так как эти значения обновить нельзя. Применение правила каскадной модификации (on delete cascade) при удалении данных о Лекторах и Курсах соответствует стратегии хранения оперативных данных. Для атрибута ДатаНач null-значения объявляются недопустимыми, так как атрибут входит в первичный ключ (объявление первичного ключа с разрешенными null-значениями в каких-либо его атрибутах СУБД не допустит). Для атрибута ДатаКон null-значения объявлены допустимыми с тем, чтобы можно было вводить данные о чтении лекций с пока не определенной датой их окончания. Ограничение кортежа (ДатаНач

<ДатаКон) не будет препятствовать вводу таких данных.

create table Лекции КодЛр integer not null, КодК integer not null, ДатаНач date not null, ДатаКон date null check(ДатаНач < ДатаКон)

primary key(КодЛ, КодК, ДатаНач)

foreign key(КодЛр) references Лекторы(КодЛр) on delete cascade

foreign key(КодК) references Курсы(КодК) on delete cascade

3.6.3. Транзакции и блокировки

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

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

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

Предположим также, что после выполнения первого из действий (уменьшения суммы денег на счете первого клиента) произошел сбой. Например, могла прерваться связь клиентского компьютера с базой данных, или на клиентском компьютере мог произойти системный сбой, что привело к перезагрузке операционной системы. Что в этом случай стало с базой данных? Команда на уменьшение денег на счете первого клиента была выполнена, а вторая команда – на увеличение денег на другом счете – нет. Без использования транзакций описанная выше ситуация привела бы к противоречивому, неактуальному состоянию базы данных.

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

торов изменения базы данных, но эти операторы либо выполняются все, либо не выполняется ни один.

Перед выполнением первого действия выдается команда начала транзакции BEGIN TRANSACTION. Поскольку после выполнения первого действия транзакция не была завершена (из-за сбоя), изменения не будут внесены в базу данных. Изменения вносятся (фиксируются) только после завершения транзакции. Оператор завершения транзакций обычно называется COMMIT TRANSACTION. До выдачи данного оператора сохранения данных в базе не произойдет. В рассматриваемом примере, поскольку оператор фиксации транзакции не был выдан, база данных откатится в первоначальное состояние – иными словами, суммы на счетах клиентов останутся те же, что и были до начала транзакции. Администратор базы данных может отслеживать состояние транзакций и в необходимых случаях вручную откатывать транзакции. Кроме того, в очевидных случаях СУБД самостоятельно принимает решение об откате транзакции. Транзакции не обязательно могут быть короткими. Бывают транзакции, которые длятся несколько часов или даже, несколько дней. Увеличение количества действий в рамках одной транзакции требует увеличения занимаемых системных ресурсов. Поэтому, желательно делать транзакции, по возможности, короткими. В журнал транзакций заносятся все транзакции – и зафиксированные и завершившиеся откатом. Ведение журнала транзакций совместно с созданием резервных копий базы данных позволяет достичь высокой надежности базы данных. Предположим, что база данных была испорчена в результате аппаратного сбоя компьютера, на котором был установлен сервер СУБД. В этом случае нужно использовать последнюю сделанную резервную копию базы данных и журнал транзакций. Причем применить к базе данных нужно только те транзакции, которые были зафиксированы после создания резервной копии. Большинство современных СУБД позволяют администратору воссоздать базу данных, исходя из резервной копии

ижурнала транзакций.

Откатом транзакций можно управлять программно, анализируя промежуточные состояния и вы-

давая команду отката транзакции ROLLBACK TRANSACTION в случае возникновения ошибочной

ситуации (на счете не хватает денег, счет для операций заблокирован и т.п.):

BEGIN TRANSACTION

UPDATE счет-1 ...

IF возникла_ошибка THEN GOTO undo UPDATE счет-2 ...

IF возникла_ошибка THEN GOTO undo COMMIT TRANSACTION

GOTO exit

undo: ROLLBACK TRANSACTION exit: ...

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

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

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

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