Добавил:
ivanov666
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз:
Предмет:
Файл:Базы данных проектирование и реализация. Учебное пособие
.pdf
когда два поля или более полей в соединении имеют одинаковые
имена в соответствующих таблицах или представлениях.
В этих случаях можно задать новые имена полей создаваемого представления, указывая их в круглых скобках после имени представления.
Типы данных и размеры выводятся из полей запроса.
Для удаления существующих представлений служит оператор
DROP VIEW. Синтаксис команды удаления представления сходен
с синтаксисом для удаления реальных таблиц:
DROP VIEW <имя представления>
Эта команда не воздействует на реальные таблицы и представления,
упомянутые в определении удаляемого представления.
Ограничения, связанные с использованием представлений:
1) представление должно базироваться на единственном запросе, т.е.
UNION и UNION ALL недопустимы;
2) ORDER ВУ нельзя использовать в определении представления.
Выходные данные для запроса, формирующего представление, должны
быть неупорядоченными по определению;
3) обновление представлений (таблиц, входящих в определение
представления) возможно, если представление является обновляемым.
Признаки обновляемого представления:
должно основываться на одной и только одной таблице;
должно включать первичный ключ таблицы;
не должно содержать полей, полученных в результате примене-
ния функций агрегирования;
не должно содержать спецификации DISTINCT в своем определе-
нии;
не должно использовать GROUP ВУ или НАVING в своем опре-
делении;
не должно использовать подзапросы;
если определение включает другое представление, то оно должно
быть также обновляемым;
не должно содержать константы, строки или выражения в списке
выбираемых полей;
для вставки записей (командой INSERT) должно включать любые
поля из лежащих в основе представления таблиц, которые имеют ограничение NOT NULL, хотя в качестве значения по умолчанию может
быть указано другое значение.
71

6. ТРАНЗАКЦИИ В БАЗЕ ДАННЫХ
В подавляющем большинстве случаев работа с базами данных происходит в многопользовательском режиме и поэтому необходимо обеспечивать такие условия, чтобы при параллельной обработке нескольких
заданий действия одних пользователей не оказывали непредусмотренного влияния на работу других, база данных всегда оставалась в согласованном состоянии.
В современных СУБД эта задача решается
низма транзакций.
Транзакция – это последовательность действий с БД, в которой
либо все действия выполняются успешно, либо не выполняется ни одно
из них (все или ничего). Транзакция является атомарной, она выполняется как единое целое.
Транзакция – совокупность связанных между собой операций, ха-
рактеризуемых четырьмя свойствами: атомарностью, непротиворечивостью, локализацией и продолжительностью [12].
Транзакцию можно рассматривать как преобразование одного логически согласованного состояния БД в другое, причем в промежуточных
точках (т. е. во время выполнения транзакции) БД может находиться
в несогласованном состоянии.
Свойства транзакции определяются аббревиатурой (принципом)
ACID – Atomicity, Consistency, Isolation, Durability [43]:
атомарность – транзакция неделима, выполняются либо все дей-
ствия, либо ничего:
согласованность (непротиворечивость) – транзакция переводит
одно согласованное состояние БД в другое, без соблюдения обязательной поддержи согласованности в промежуточных точках;
изоляция (локализация) – даже если запущено несколько конку-
рирующих между собой транзакций, любое обновление, выполненное
с использованием меха-
72

одной из транзакций, будет скрыто от остальных до тех пор, пока сделавшая изменения транзакция не будет зафиксирована. Результаты транзакции становятся доступны для других транзакций только после ее фиксации;
долговечность (продолжительность) – когда транзакция выпол-
нена, ее обновления сохраняются, даже если в следующий момент произойдет сбой системы.
6.1. ПРОБЛЕМЫ ПАРАЛЛЕЛЬНОГО ДОСТУПА
Если не принимать соответствующих мер, то при выполнении нескольких транзакций, обращающихся к одним и тем же данным (конкурирующим транзакциям), могут возникнуть следующие проблемы:
потерянное обновление – несколько пользователей изменяют
одну и ту же строку, основываясь на ее начальном значении, в результате часть данных будет потеряна, так как каждая последующая транзакция перезапишет изменения, сделанные предыдущей;
«грязное» чтение может возникнуть при чтении транзакцией за-
писи, которая изменена, но еще не сохранена в БД (данные изменены
еще не завершившейся транзакцией, которая после будет отменена);
неповторяемое чтение – при повторном чтении данных, уже счи-
танных ранее, транзакция обнаруживает модификации или удаления,
вызванные другой завершенной транзакцией; подобное изменение может нарушить логику работы транзакции;
чтение фантомов появляется, когда при повторном чтении данных
транзакция обнаруживает новые строки, вставленные или измененные
другой транзакцией, завершенной после предыдущего чтения этого
набора данных.
Рассмотрим ситуации, в которых возможно возникновение данных
проблем.
Потерянное обновление – при одновременном изменении одного
блока данных разными транзакциями одно из изменений теряется.
Предположим, имеются две транзакции, выполняемые одновременно.
Транзакция 1 Транзакция 2
UPDATE tbl1 SET f2=f2+20 WHERE f1=1; UPDATE tbl1 SET f2=f2+25 WHERE f1=1;
В обеих транзакциях изменяется значение поля f2, по их завершении
значение поля должно быть увеличено на 45. В действительности может
возникнуть следующая последовательность действий.
73

Обе транзакции одновременно читают текущее состояние поля.
1.
Точная физическая одновременность здесь не обязательна, достаточно,
чтобы вторая по порядку операция чтения выполнилась до того как другая транзакция запишет свой результат.
Обе транзакции вычисляют новое значение поля, прибавляя соот-
2.
ветственно 20 и 25 к ранее прочитанному значению.
Транзакции пытаются записать результат вычислений обратно
3.
в поле f2. Поскольку физически одновременно две записи выполнить
невозможно, в реальности одна из операций записи будет выполнена
раньше, другая позже. При этом вторая операция записи перезапишет
результат первой.
В результате значение поля f2 по завершении обеих транзакций может увеличиться не на 45, а на 20 или 25, т
. е. одна из изменяющих дан-
ные транзакций «пропадет».
«Грязное» чтение – чтение данных, добавленных или измененных
транзакцией, которая впоследствии не подтвердится (откатится).
Предположим, имеются две транзакции, открытые различными приложениями, в которых выполнены следующие SQL-операторы:
Транзакция 1 Транзакция 2
UPDATE tbl1 SET f2=f2+1 WHERE f1=1;
SELECT f2 FROM tbl1 WHERE f1=1;
ROLLBACK TRANSACTION
В транзакции 1 изменяется значение поля f2, а затем в транзакции 2
выбирается значение этого поля. После этого происходит откат транзакции 1. В результате значение, полученное второй транзакцией, будет отличаться от значения, хранимого в базе данных.
Неповторяющееся чтение – при повторном чтении в рамках одной
транзакции ранее прочитанные данные оказываются измененными.
Предположим, имеются две транзакции, открытые различными приложениями, в которых выполнены следующие SQL-операторы.
Транзакция 1 Транзакция 2
SELECT f2 FROM tbl1 WHERE f1=1;
UPDATE tbl1 SET f2=f2+1 WHERE f1=1;
COMMIT TRANSACTION
SELECT f2 FROM tbl1 WHERE f1=1;
74

В транзакции 2 выбирается значение поля f2, затем в транзакции 1
изменяется значение поля f2. При повторной попытке выбора значения
из поля f2 в транзакции 2 будет получен другой результат. Эта ситуация
особенно неприемлема, когда данные считываются с целью их частичного изменения и обратной записи в базу данных.
Чтение «фантомов» – при повторном чтении в рамках одной транз-
акции одна и та же выборка дает несовпадающие множества строк.
Предположим, имеется две транзакции, открытые различными приложениями, в которых выполнены следующие SQL-операторы.
Транзакция 1 Транзакция 2
SELECT SUM(f2) FROM tbl1;
INSERT INTO tbl1 (f1,f2) VALUES (15,20);
COMMIT TRANSACTION
SELECT SUM(f2) FROM tbl1;
В транзакции 2 выполняется SQL-оператор, использующий все значения поля f2. Затем в транзакции 1 выполняется вставка новой строки,
приводящая к тому, что повторное выполнение SQL-оператора в транзакции 2 выдаст другой результат. Такая ситуация называется чтением
фантома (фантомным чтением). От неповторяющегося чтения оно отличается тем, что результат повторного обращения к данным изменился
не
из-за изменения/удаления самих этих данных, а из-за появления но-
вых (фантомных) данных.
6.2. УПРАВЛЕНИЕ ТРАНЗАКЦИЯМИ
Для управления транзакциями используется подмножество языка
SQL – набор команд (TCL), позволяющих управлять транзакциями –
группами команд, которые все должны завершиться успешно. В случае
неудачного завершения хотя бы одной команды из транзакции транзакция откатывается к началу, восстанавливая состояние базы данных на
момент начала транзакции, либо к предшествующей точке сохранения
(отменяются результаты выполнения предыдущих
команд).
1. START TRANSACTION – обозначает начало транзакции.
2. COMMIT TRANSACTION – подтверждает выполнение команд
внутри транзакции.
3.
ROLLBACK TRANSACTION – отменяет все сделанные внутри
транзакции изменения (откатывает транзакцию).
75

SAVEPOINT – создает точку сохранения в пределах транзакции.
4.
Точка сохранения представляет собой место в последовательности команд транзакции, которое может выступать в качестве промежуточной
точки сохранения. Откат текущей транзакции может быть выполнен не
к началу транзакции, а к точке сохранения.
5.
RELEASE SAVEPOINT – удаляет ранее определенную точку со-
хранения.
Существует два типа транзакций.
Неявная транзакция – по умолчанию каждая команда модифика-
ции данных (INSERT, UPDATE или DELETE) выполняется как самостоятельная транзакция, команды DDL и DCL сами являются транзакциями.
Явная транзакция – последовательность команд работы с данными,
начало которой должно быть обозначено как START TRANSACTION,
а конец транзакции командой COMMIT TRANSACTION, если в теле
транзакции не было ошибок (сохраняются все сделанные в ходе транзакции изменения), или ROLLBACK TRANSACTION, если произошел сбой
(отменяются все изменения, сделанные в БД после оператора START
TRANSACTION или после последней зафиксированной точки сохране
-
ния).
Вложеннная транзакция – транзакции, выполнение которых ини-
циируется из тела уже активной транзакции. Вложенная транзакция может быть:
автономной – полностью независимой от транзакции, внутри ко-
торой она была создана. Ее результаты фиксируются и откатываются
независимо от внешней транзакции. Такая транзакция может нарушать
принципы Atomicity и Consistency при возникновении ошибок во внешней или вложенной транзакции;
зависимой – при фиксации вложенной транзакции (COMMIT
TRANSACTION) окончательный результат зависит от результата внеш-
ней транзакции (может нарушаться свойство Durability): если внешняя
транзакция заканчивается успешно, то и результат внутренней транзакции также фиксируется. Если же при выполнении внешней транзакции
происходит ошибка, то внутренняя транзакция также откатывается,
а если внутренняя транзакция заканчивается неуспешно, то внешняя
транзакция тоже должна откатиться.
В общем случае использование вложенных транзакций не рекомендуется, хотя некоторые СУБД поддерживают механизм вложенных
транзакций (SQL Server)
. Точки сохранения позволяют имитировать ме-
ханизм вложенных транзакций,
76

6.3. УРОВНИ ИЗОЛЯЦИИ ТРАНЗАКЦИЙ
Чтобы избежать подобных проблем, необходимо обеспечить изоляцию транзакций. Для этого в стандарте SQL-92 определены четыре
уровня изоляции транзакций.
READ UNCOMMITTED (незавершенное чтение) позволяет избе-
жать только потерянного обновления. Этот уровень требует, чтобы изменять данные могла только одна транзакция; если другой транзакции
необходимо изменить те же данные, она должна ожидать завершения
первой транзакции.
READ COMMITTED (завершенное чтение) дополнительно позво-
ляет избежать «грязного» чтения. Если транзакция начала изменение
данных, то никакая другая транзакция не сможет прочитать их до завершения первой.
REPEATABLE READ (повторяющееся чтение) в дополнение обес-
печивает повторяемость чтения: если транзакция считывает данные, то
никакая другая транзакция не сможет их изменить, и при повторном
чтении они будут находиться в том же состоянии.
SERIALIZABLE (сериализуемость), самый высокий уровень, поз-
воляющий справиться с проблемой чтения фантомов. Если транзакция
обращается к данным, то никакая другая транзакция не сможет добавить
новые или изменить существующие строки, которые могут быть считаны при выполнении транзакции.
Сериализуемость означает, что две транзакции обрабатываются параллельно таким образом, что их результаты согласуются
с результатами, которые могут быть получены при последовательной обработке
этих транзакций.
В таблице перечислены уровни изоляции транзакций и решаемые
с их помощью проблемы.
«+» – предотвращает, «–» – не предотвращает.
Уровень изоляции
SERIALIZABLE + + + +
REPEATABLE READ – + + +
READ COMMITTED – – + +
READ UNCOMMITTED – – – +
Фантомное
чтение
Неповторяю-
щееся чтение
77
«Грязное»
чтение
Потерянное
обновление
[3]

6.4. БЛОКИРОВКИ ПРИ РЕАЛИЗАЦИИ
МЕХАНИЗМА ТРАНЗАКЦИЙ
Основное средство реализации уровней изоляции – блокировка объ-
ектов базы данных.
Блокировкой называется временное ограничение на выполнение некоторых операций обработки данных. Блокировки могут налагаться
либо автоматически, по инициативе СУБД, либо командой, которая отдается прикладной программой или запросом пользователя. Налагаемые СУБД блокировки называются
кировки, налагаемые по команде пользователя, –
ками
.
Размер блокируемого объекта называется
блокировки
. При большей глубине детализации, т. е. при блокировке
неявными блокировками, а бло-
явными блокиров-
глубиной детализации
более крупных объектов (например, таблиц), СУБД лучше справляется
с управлением блокировки, но такие блокировки чаще вызывают конфликты. При уменьшении размера блокируемого фрагмента вероятность возникновения конфликта снижается, но такими блокировками
сложнее управлять: СУБД необходимо отслеживать гораздо больше деталей.
Поскольку действия,
выполняемые пользователями при работе
с данными, сводятся к операциям двух типов: чтению и изменению
(в операции по изменению включаются действия по добавлению, удалению и собственно изменению данных), в зависимости от выполняемых
действий СУБД накладывает определенный тип блокировки из следующего перечня:
блокировка записи – транзакция блокирует строки в таблицах та-
ким образом, что запрос другой транзакции к этим строкам будет отменен;
блокировка чтения – транзакция блокирует строки так, что запрос
со стороны другой транзакции на блокировку записи этих строк будет
отвергнут, а на блокировку чтения – принят.
Механизм наложения блокировок представляет собой протокол доступа к данным, позволяющий избежать проблем параллелизма. Его
суть заключается в следующем:
транзакция, результатом действия которой на строку данных
в таблице является ее извлечение, обязана наложить блокировку чтения
на эту строку;
78

транзакция, предназначенная для модификации строки данных,
накладывает на нее блокировку записи;
если запрашиваемая блокировка на строку отвергается из-за уже
имеющейся блокировки, то транзакция переводится в режим ожидания
до тех пор, пока блокировка не будет снята;
блокировка записи сохраняется вплоть до конца выполнения
транзакции.
«Мертвые» блокировки
В некоторых случаях может возникать ситуация взаимной блокировки (англ. deadlock), когда две транзакции блокируют необходимые
им данные и для завершения любой из них нужен доступ к данным, заблокированным ранее другой транзакцией. Для завершения каждой
транзакции необходимо дождаться, пока блокированная другой транзакцией часть данных будет разблокирована. Но это невозможно, так
как
вторая транзакция ожидает разблокирования данных, используемых
первой.
Для разрешения конфликтов блокировок СУБД должна отслеживать
появление «мертвых» блокировок и снимать одну из блокировок, вызвавших конфликт, и откатывать инициализировавшую ее транзакцию.
При выборе блокировки, которой необходимо пожертвовать, СУБД исходит из соображений минимальной стоимости.
Полностью избежать возникновения «мертвых» блокировок нельзя.
Поэтому при создании приложений следует учитывать вероятность их
возникновения и предпринимать все возможные действия для предупреждения этого. «Мертвые» блокировки могут существенно снизить производительность, поскольку системе требуется довольно много времени
для их обнаружения, отката транзакции и повторного ее выполнения.
Для минимизации возможности образования «мертвых» блокировок
при разработке кода транзакции следует
придерживаться следующих
правил:
выполнять действия по обработке данных в постоянном порядке,
чтобы не создавать условия для захвата одних и тех же данных;
избегать взаимодействия с пользователем в теле транзакции;
минимизировать длительность транзакции и выполнять ее по воз-
можности в одном пакете;
использовать небольшие транзакции, т. е. включающие как
можно меньше команд и изменяющие минимум данных;
79

применять как можно более низкий уровень изоляции, поскольку
высокий уровень изоляции транзакций приводит к большему числу блокировок и снижает общую производительность системы.
Отметим, что различные СУБД могут реализовывать различающиеся наборы уровней изоляции.
80
Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]
