Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Базы данных проектирование и реализация. Учебное пособие

.pdf
Скачиваний:
0
Добавлен:
07.09.2026
Размер:
2 Мб
Скачать
когда два поля или более полей в соединении имеют одинаковые
имена в соответствующих таблицах или представлениях.
В этих случаях можно задать новые имена полей создаваемого пред­ставления, указывая их в круглых скобках после имени представления. Типы данных и размеры выводятся из полей запроса.
Для удаления существующих представлений служит оператор
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
Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]