Лекции ПрБД, 2 курс 3 семестр (для ИВТ и т.п.) / Проектирование БД_уч пособие v02
.pdf
Наиболее распространенным механизмом, который используется коммерческими СУБД для реализации на практике сериализации транзакций является механизм блокировок. Самый простой вариант – это блокировка объекта на все время действия транзакции. Подобный пример рассмотрен на Рис. 56. Здесь две транзакции, названные условно А и В, работают с тремя таблицами: Т1, Т2 и Т3. В момент начала работы с любым объектом этот объект блокируется транзакцией, которая с ним начала работу, и он становится недоступным всем другим транзакциям до окончания транзакции, заблокировавшей («захватившей») данный объект. После окончания транзакции все заблокированные ею объекты разблокируются и становятся доступными другим транзакциям. Если транзакция обращается к заблокированному объекту, то она остается в состоянии ожидания до момента разблокировки этого объекта, после чего она может продолжать обработку данного объекта. Поэтому транзакция В ожидает разблокировки таблицы Т2 транзакцией А. Над прямоугольниками стоит условное время выполнения операций.
Транзакция А |
T1 |
T1 |
T1 |
Транзакция B |
|
разблокирована |
разблокирована |
разблокирована |
|||
|
|
||||
10:01 |
|
|
|
|
|
Update T1 |
Заблокирована |
|
|
10:02 |
|
для А |
|
Заблокирована |
|
||
|
|
Update T1 |
|||
10:03 |
|
|
для B |
||
|
|
|
|||
|
|
|
|
||
|
|
Заблокирована |
|
|
|
Update T2 |
|
для А |
|
|
|
|
|
|
|
10:04 |
|
10:05 |
|
|
Ожидание |
Update T2 |
|
|
|
|
|
||
Update T1 |
|
|
|
|
|
10:06 |
|
|
|
|
|
Update T2 |
|
|
|
|
|
10:07 |
|
|
|
|
|
Commit |
Разблокирована |
Разблокирована |
|
10:07 |
|
|
|
|
|
||
|
Заблокирована |
Заблокирована |
|
|
|
|
для В |
для В |
|
|
|
|
|
|
|
10:08 |
|
|
Разблокирована |
Разблокирована |
Разблокирована |
Commit |
|
|
|
||||
Рис. 56. Блокировки при одновременном выполнении двух транзакций |
|||||
211
В общем случае на момент выполнения транзакция получает как бы монопольный доступ к объектам БД, с которыми она работает. В этом случае другие транзакции не получают доступа к объектам БД до момента окончания транзакции. Такой механизм действительно ликвидирует все перечисленные ранее проблемы: пропавшие изменения, неподтвержденные данные, несогласованные данные, строки-фантомы. Однако такая блокировка создает новые проблемы – задержку выполнения транзакций из-за блокировок.
Рассмотрим существующие типы конфликтов между двумя параллельными транзакциями. Можно выделить следующие типы:
−W-W – транзакция 2 пытается изменять объект, измененный незакончившейся транзакцией 1;
−R-W – транзакция 2 пытается изменять объект, прочитанный незакончившейся транзакцией 1;
−W-R – транзакция 2 пытается читать объект, измененный неза-
кончившейся транзакцией 1.
Практические методы сериализации транзакций основываются на учете этих конфликтов.
Блокировки, называемые также синхронизационными захватами объектов, могут быть применены к разному типу объектов. Наибольшим объектом блокировки может быть вся БД, однако этот вид блокировки сделает БД недоступной для всех приложений, которые работают с данной БД. Следующий тип объекта блокировки – это таблицы.
Транзакция, которая работает с таблицей, блокирует ее на все время выполнения транзакции (Табл. 13).
Этот вид блокировки предпочтительнее предыдущего, потому что позволяет параллельно выполнять транзакции, которые работают с другими таблицами.
В ряде СУБД реализована блокировка на уровне страниц. В этом случае СУБД блокирует только отдельные страницы на диске, когда транзакция обращается к ним. Этот вид блокировки еще более мягок и позволяет разным транзакциям работать даже с одной и той же таблицей, если они обращаются к разным страницам данных.
212
Табл. 13. Правила применения жесткой и нежесткой блокировок транзакций
|
|
|
Транзакция В |
|
|
|
|
|
|
|
|
|
|
Разблокирована |
Нежесткая |
Жесткая |
|
|
|
|
блокировка |
блокировка |
|
|
|
|
|
|
|
|
Разблокирована |
да |
да |
да |
|
|
|
|
|
|
|
|
Нежесткая |
да |
да |
нет |
|
Транзакция А |
блокировка |
||||
|
|
|
|||
|
|
|
|
|
|
|
Жесткая |
да |
нет |
нет |
|
|
блокировка |
||||
|
|
|
|
||
|
|
|
|
|
В некоторых СУБД возможна блокировка на уровне строк, однако такой механизм блокировки требует дополнительных затрат на поддержку этого вида блокировки.
Для повышения параллельности выполнения транзакций используется комбинирование разных типов синхронизационных захватов.
Рассматривают два типа блокировок (синхронизационных захва-
тов):
−совместный режим блокировки – нежесткая, или разделяемая, блокировка, обозначаемая как S (Shared). Этот режим обозначает разделяемый захват объекта и требуется для выполнения операции чтения объекта. Объекты, заблокированные таким образом, не изменяются в ходе выполнения транзакции и доступны другим транзакциям также, но только в режиме чтения;
−монопольный режим блокировки – жесткая, или эксклюзивная, блокировка, обозначаемая как X (eXclusive). Данный режим блокировки предполагает монопольный захват объекта и требуется для выполнения операций занесения, удаления и модификации. Объекты, заблокированные данным типом блокировки, фактиче-
ски остаются в монопольном режиме обработки и недоступны для других транзакций до момента окончания работы данной транзакции.
Захваты объектов несколькими транзакциями по чтению совместимы, то есть нескольким транзакциям допускается читать один и тот же объект, захват объекта одной транзакцией по чтению не совместим с захватом другой транзакцией того же объекта по записи, и захваты одного
213
объекта разными транзакциями по записи не совместимы. Правила совместимости захватов одного объекта разными транзакциями изображены в Табл. 13.:
В примере, представленном в Табл. 13 считается, что первой блокирует объект транзакция А, а потом пытается получить к нему доступ транзакция В.
На Рис. 57 приведен ранее рассмотренный пример с выполнением транзакций 1 и 2, но с учетом разных типов блокировки. На рисунке видно, что, применив нежесткую блокировку к таблице 2 со стороны транзакции 1, мы обеспечили существенное уменьшение времени выполнения транзакции 2. Теперь транзакция 2 не ждет окончания транзакции 1, и поэтому завершает свою работу намного раньше.
Транзакция А |
T1 |
T1 |
T1 |
Транзакция B |
||
разблокирована |
разблокирована |
разблокирована |
||||
|
|
|
||||
10:01 |
|
|
|
|
10:02 |
|
|
|
Жесткая |
Нежёсткая |
|
||
Update T1 |
|
|
|
|||
|
блокировка для А |
блокировка для А |
Заблокирована |
Update T1 |
||
|
|
|||||
|
|
|
|
для B |
|
|
10:03 |
|
|
|
|
|
|
Select F2 |
|
|
Нежёсткая |
|
10:04 |
|
|
|
блокировка для А и B |
|
|
||
|
|
|
|
|
||
|
|
|
|
|
Update T2 |
|
10:05 |
|
|
Нежёсткая |
|
|
|
|
|
блокировка для А |
|
10:05 |
||
Update T1 |
|
|
|
Разблокирована |
Commit |
|
|
|
|
Нежёсткая |
|
|
|
|
|
|
блокировка для А |
|
|
|
10:06 |
|
|
|
|
|
|
Update F2 |
|
|
Жесткая блокировка |
|
|
|
|
|
|
|
|
||
|
|
|
для А |
|
|
|
10:07 |
|
|
|
|
|
|
Commit |
|
Разблокирована |
Разблокирована |
|
|
|
|
|
|
|
|||
|
Рис. 57. Использование жесткой и нежесткой блокировки |
|||||
К сожалению, применения разных типов блокировок приводит к проблеме тупиков. Проблема тупиков возникла при рассмотрении выполнения параллельных процессов в операционных средах и также была связана с управлением разделяемыми (совместно используемыми) ресурсами.
Действительно, рассмотрим пример. Пусть транзакция А сначала жестко блокирует таблицу 1, а потом жестко блокирует таблицу 2. Транзакция B, наоборот, сначала жестко блокирует таблицу 2, а потом жестко
214
блокирует таблицу 1. Если обе эти транзакции начали работу одновременно, то после выполнения операций модификации первыми объектами каждой транзакции они обе окажутся в бесконечном ожидании: транзакция А будет ждать завершения работы транзакции B и разблокировки таблицы 2, а транзакция В также безрезультатно будет ждать окончания работы транзакции А и разблокировки таблицы 1 (см. Рис. 58).
Транзакция А
10:01
Update T1
10:03
Update T2
T1 |
T2 |
Транзакция B |
|
|
10:02 |
Жесткая |
|
Update T2 |
блокировка для А |
|
|
Жесткая |
|
|
|
|
|
|
блокировка для B |
10:04 |
|
|
|
|
|
Update T1 |
Ожидание |
|
|
|
Ожидание |
|
Рис. 58. Взаимная блокировка транзакций |
|
|
Ситуации могут быть гораздо более сложными. Количество взаимно заблокированных транзакций может оказаться гораздо больше. Эту ситуацию каждая из транзакций обнаружить самостоятельно не может. Ее должна разрешить СУБД. И действительно, в большинстве коммерческих СУБД существует механизм обнаружения таких тупиковых ситуаций.
Основой обнаружения тупиковых ситуаций является построение (или постоянное поддержание) графа ожидания транзакций.
Вопросы для самопроверки
1)В чем заключается модель транзакций ANSI/ISO?
2)То такое журнал транзакций?
3)Перечислите принципы восстановления после сбоя.
4)Что такое индивидуальный откат транзакции?
5)Каков механизм восстановления при индивидуальном откате?
6)Что такое мягкий сбой?
7)Каков механизм восстановления при мягком сбое?
8)Что такое жесткий сбой?
9)Каков механизм восстановления при жестком сбое?
215
13Денормализация
13.1Понятие о денормализации
|
процесс достижения компромиссов в нормализован- |
|
|
ДЕНОРМАЛИЗАЦИЯ |
ных таблицах посредством намеренного введения |
|
избыточности в целях увеличения производительно- |
|
сти |
|
|
|
|
В большинстве случаев необходимость денормализации становится очевидной лишь на этапе проектирования модуля. Т.е. обычно нельзя принять решение о денормализации на основании одной только модели данных. Когда проектировщик принимает решение о денормализации, то он должен руководствоваться здравым смыслом. Обычно стараются найти в приложении БД критичные процессы и принимать решения о денормализации в основном в пользу этих процессов. Критичные процессы обычно определяют по высокой частоте, большому объему, высокой изменчивости или явному приоритету. Если проектировщик БД прописал все транзакции БД, то он, вероятно, сможет определить наличие таких критических процессов.
Использовать денормализацию только для упрощения SQLзапросов при обращении к БД является неправильным решением. Если необходимо упростить SQL-запросы на уровне приложения или пользователя, то лучше использовать представления, а не вводить избыточность. Чтобы повысить производительность запроса, можно ввести индексы [22].
Как правило, денормализация уменьшает время запроса за счет DML-операций. Денормализацию следует рассматривать как расширение нормализованной модели данных, которое повысит производительность запросов. При принятии решения о денормализации определите, что является наиболее важным для приложения – избыточность данных или высокая производительность. Если проектировщик БД ведет журнал проектирования (некоторый внутренний документ произвольной формы, в котором фиксируются все принятые в процессе проектирования БД решения), то в него необходимо занести обоснованное решение о денормализации. Денормализацию таблиц можно выполнять как на уровне логической модели данных, так и на уровне физической модели.
216
13.2 Нисходящая денормализация
Рассмотрим принципы денормализации на уровне логической модели реляционной базы данных.
Нисходящая денормализация предлагает перенос атрибута из одной (родительской) сущности в подчиненную (дочернюю) сущность (Рис. 59 – Рис. 60). В денормализованной логической модели переместили фамилию клиента из сущности Customer (Клиент) в сущность Order (Заказ).
Customer |
|
|
|
|
|
Order |
|
|
|
|
|
|
|
ID |
|
|
|
|
|
Order_no |
Address |
|
|
|
|
|
Date taken |
|
|
make order |
||||
Name |
|
|
|
|
|
Date dispatched |
Tel |
|
|
|
|
|
Date invoiced |
|
|
|
|
|
|
CUS_ID |
|
|
|
|
|
|
|
Рис. 59. Сущности Customer и Order до денормализации
Customer |
|
|
|
|
|
|
Order |
|
|
|
|
|
|
|
|
|
|
ID |
|
|
|
|
|
|
Order_no |
|
Address |
|
|
make order |
|
Date taken |
|||
Name |
|
|
|
|
|
|
Date dispatched |
|
Tel |
|
|
|
|
|
|
Date invoiced |
|
|
|
|
|
|
|
|
CUS_ID |
|
|
|
|
|
|
|
|
CUS_Name |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Рис. 60. Сущности Customer и Order после денормализации
Что дает введение избыточности (перенос атрибута) в данном случае? Единственный выигрыш заключается в том, что мы исключаем операцию соединения, если захотим вместе с заказом увидеть фамилию клиента.
Таким образом, нисходящая денормализация – это процесс введения избыточных колонок в подчиненных таблицах с целью устранения операций соединения.
Однако устранение соединений посредством нисходящей денормализации редко оправдывает затраты на сопровождение дублирующей колонки в таблице ORDER. Такие соединения, как правило, не являются глобальной проблемой, а выполнение нисходящей денормализации может
217
привести к возникновению дорогостоящих каскадных обновлений, дающих небольшую реальную выгоду. Например, если клиент меняет фамилию, то приходится обновлять все заказы, чтобы отразить это изменение. А нужно ли это делать? Следует ли обновлять старые заказы, которые выполнены или закрыты? Если бы не была проведена денормализация, то эти вопросы никогда бы и не возникли.
Нисходящая денормализация оправдана лишь в приложениях, где необходимо устранять операции соединения таблиц. Это имеет место в БД большого объема, таких как хранилища данных. При этом проблемы с каскадными обновлениями не возникает потому, что данные в хранилищах данных – архивные.
13.3 Восходящая денормализация
Восходящая денормализация предлагает перенос атрибута из подчиненной (дочерней) сущности в родительскую сущность, обычно в форме итоговых данных (Рис. 61 – Рис. 62).
Order |
|
|
|
|
|
|
OrderItem |
|
|
|
|
|
|
|
|
|
|
Order_no |
|
|
|
|
|
|
ORD Order_no |
|
Date taken |
|
|
|
|
|
|
|
Item_no |
Date dispatched |
|
|
from order |
|
ItemPrice |
|||
|
|
|
|
|
|
|||
Date invoiced |
|
|
|
|
|
|
NO_Ordered |
|
CUS_ID
CUS_Name
Рис. 61. Сущности Customer и Order до денормализации
|
Order |
|
|
|
|
|
OrderItem |
|
|
|
|
|
|
|
|
|
|
|
Order_no |
|
|
|
|
|
ORD Order_no |
|
|
Date taken |
|
|
|
|
|
Item_no |
|
|
Date dispatched |
|
|
from order |
ItemPrice |
|||
|
|
|
|
|
|
|||
|
Date invoiced |
|
|
|
|
|
NO_Ordered |
|
|
CUS_ID |
|
|
|
|
|
|
|
|
CUS_Name |
|
|
|
|
|
|
|
|
Order_Price |
|
|
|
|
|
|
|
|
|
|
|
|
|
|||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Рис. 62. Сущности Customer и Order после денормализации
218
Рассмотрим две сущности Order и Order Item (Позиция заказа). Например, если при вычислении общей суммы заказа в системе обработки заказов (суммирование колонок Item_Price в таблице Order Item) приводит к снижению производительности, то можно повысить производительность этой операции, поместив сумму заказа в избыточном столбце таблицы ORDER. В нашем примере в избыточном столбце хранится сумма значений, но эти приемы применимы к максимальным, минимальным и средним значениям, а также к другим агрегатным показателям.
Таким образом, восходящая денормализация – это процесс введения избыточных колонок в родительских таблицах с целью устранения операций соединения с операциями агрегирования.
Чтобы представить последствия введения денормализации, рассмотрим процедуру сопровождения денормализованных таблиц Order и Order Item, которые сводятся к поддержке следующих бизнес-правил:
−когда в таблицу Order Item добавляется новая строка, то цена заказа (колонка Order_Price) в таблице Order увеличивается на цену новой позиции заказа (Item_Price);
−когда строка удаляется из таблицы Order Item, то цена заказа в таблице Order уменьшается на цену старой позиции заказа (Item_Price);
−когда изменяется цена в таблице Order Item, то цена заказа в таб-
лице Order должна быть откорректирована на разницу между старой и новой ценами позиции заказа (Item_Price).
Поддержка перечисленных выше бизнес-правил создает дополнительную нагрузку на процессы, выполняющие DML -операции в таблице Order Item.
13.4 Внутритабличная денормализация
Внутритабличная денормализация выполняется в пределах одной таблицы, т.е. это процесс введения избыточных колонок в одной таблице с целью увеличения производительности запроса строки по производному значению.
Например, если строка содержит две числовых колонки, X и Y, то значение Z, равное произведению X и Y (Z = X*Y), легко вычислить во время выполнения.
219
Однако предположим, что есть запросы, в которых необходимо осуществить поиск по Z (например, Z принадлежит диапазону от 10 до 20). Сохранив избыточные значения Z в столбце, можно построить индекс по Z, и запросы будут использовать этот индекс. Если индекс по Z строить не надо, то решение о его хранении в отдельном столбце зависит от того, что является более приемлемым – увеличение времени загрузки, вызванное необходимостью постоянно пересчитывать Z, или увеличение времени сканирования, обусловленное удлинением строк таблицы за счет хранения дополнительной колонки.
13.5 Денормализация методом «разделяй и властвуй»
Денормализация методом «разделяй и властвуй» – это процесс разбиения нормализованной таблицы на две и более таблиц и создание между ними отношения «один к одному» с целью устранения дополнительных операций ввода/вывода или по техническим причинам.
Использование этого приема носит причины технического характера. Во многих СУБД таблица не может иметь больше одного столбца типа LONG или LONG RAW. Допустим, что у вас есть таблица Films и нужно сохранить и окончательный вариант фильма (LONG), и вариант, который отсняли с множеством дублей (LONG RAW). Из-за вышеупомянутого ограничения в одной таблице это сделать нельзя, поэтому один из кодов нужно разместить в отдельной таблице. Проектировщику базы данных не остается ничего другого как разбить таблицу на две.
Иногда лучше вынести столбец LONG в отдельную таблицу, даже если вышеупомянутое ограничение не действует. Рассмотрим таблицу, строки которой содержат в начале ключевые колонки, потом неключевые колонки, а в конце – колонку типа LONG. Предположим, что в большинстве строк столбец LONG содержит данные. Если нет индексов по неключевым столбцам, то при выполнении запросов по любому из этих столбцов СУБД обычно будет осуществлять полное сканирование таблицы. При этом из-за наличия в таблице столбца LONG понадобятся дополнительные операции ввода/вывода. Чтобы устранить эту проблему, разделите таблицу так, как показано на Рис. 63.
220
