Главная страница
Навигация по странице:

  • USE

  • COMMIT

  • COMMIT ) ошибочное завершение программы прерывает транзакцию (как ROLLBACK

  • Неповторяемое (размытое) чтение

  • Фантом (фиктивные элементы)

  • Уровень изоляции Грязное чтение Размытое чтение Фантом

  • SET TRANSACTION , Список уровней изоляции приведен в таблице. Режим доступа по умолчанию используется READ WRITE

  • База данных-понятия. Классификация по


    Скачать 0.55 Mb.
    НазваниеКлассификация по
    АнкорБаза данных-понятия.docx
    Дата17.07.2018
    Размер0.55 Mb.
    Формат файлаdocx
    Имя файлаБаза данных-понятия.docx
    ТипДокументы
    #21614
    страница13 из 23
    1   ...   9   10   11   12   13   14   15   16   ...   23

    4.8.Навигационный подход к манипулированию данными и персональные СУБД.


    Обсуждая вопрос практического написания приложений, взаимодействующих с реляционными базами данных (см. раздел 4.7.1), мы обнаружили один любопытный факт: для пользовательского приложения очень важна обработка не реляционного отношения в целом, как множества неупорядоченных строк, а именно каждой отдельной строки. Для этого служат функции DB_next, DB_prev и прочие, позволяющие перемещаться по строкам. При этом возможен доступ к значениям полей только одной строки, той которая является "текущей". Такой подход к манипулированию данными, при котором пользователь (или его программа) явно различает "предыдущие" и "последующие" строки и может управлять перемещением указателя от одной строки к другой, получил название навигационного (напомним, что навигационный подход типичен для сетевых и иерархических СУБД).

    Ясно, что без навигационного подхода при создании клиентского приложения обойтись невозможно, в то же время для взаимодействия с сервером базы данных предлагается язык SQL как более эффективный. Однако, существует ряд СУБД, в которых навигационный подход распространен и на манипулирование хранимыми данными. Такие системы (dBase, FoxPro, Paradox) появились в начале 80-х годов и были предназначены для создания небольших однопользовательских приложений.

    Рассмотрим кратко язык xBase, который поддерживается такими СУБД как dBase, FoxPro, Clipper и, возможно, некоторыми другими. Помимо собственно процедурных операторов (цикл, условие и т.п.) он включает операторы создания пользовательского интерфейса (меню, окна, экранные формы,...). Для работы с данными служит следующий набор команд:

    • USE <имя_таблицы> - открыть таблицу. При этом одна строка таблицы считается "текущей". К полям "текущей" строки можно обращаться по их именам.

    • GO [ TOP | BOTTOM ] - сделать "текущей" первую / последнюю запись таблицы.

    • SKIP - сделать текущей следующую запись.

    • REPLACE <имя_столбца> WITH <значение> [,<имя_столбца> WITH <значение> ...] - изменить значения полей текущей записи

    Существуют также команды экранного редактирования записей (EDIT, BROWSE), поиска данных в таблице (FIND) и другие. Приведем пример небольшой программы на языке xBase, которая распечатывает таблицу authors, а затем добаляет в нее новую строку:

    USE AUTHORS /* Открыть таблицу authors */

    GO TOP /* Перейти на первую запись */

    DO WHILE .NOT.EOF() /* Выполнять цикл пока не будет достигнут конец таблицы */

    PRINT AUTHOR /* Напечатать содержимое поля author */

    SKIP /* Перейти на следующую запись */

    ENDDO /* Конец цикла */
    APPEND BLANK /* Добавить пустую запись. Она автоматически становится текущей */

    REPLACE AU_ID WITH 90, AUTHOR WITH "L.Pinter" /* Изменить значения полей текущей записи */

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

    С развитием компьютерных сетей персональные СУБД стали переходить в разряд многопользовательских. При этом файлы данных размещались на разделяемом сетевом диске. Однако, создание достаточно больших приложений (10-20 одновременно работаюших пользователей) показало, что в этом случае резко снижается производительность и возникают проблемы с поддержанием целостности (точнее с изоляцией пользователей, подробнее см. следующий параграф). Поэтому, в настоящее время практически все персональные СУБД дополнены средствами доступа к SQL-серверам (как правило, с использованием ODBC). Теперь они могут служить не только средством для создания небольших локальных приложений, но и для разработки клиентских рабочих мест в архитектуре "клиент-сервер".

    4.9.Транзакции, блокировки и многопользовательский доступ к данным.


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

    • В банковской системе производится перевод денежных средств с одного счета на другой. На языке SQL эта операция описывается последовательностью двух команд UPDATE:

    • UPDATE accounts SET summa=summa-1000 WHERE account="PC_1"

    UPDATE accounts SET summa=summa+1000 WHERE account="PC_2"

    Как видим, после выполнения первой команды и до завершения второй команды база данных не находится в целостном состоянии (искомая сумма списана с первого счета, но не зачислена на второй). Если в этот момент в системе произойдет сбой (например, выключение электропитания), то целостное состояние БД будет безвозвратно утеряно.

    • Целостность БД может нарушаться и во время обработки одной команды SQL. Пусть выполняется операция увеличения зарплаты всех сотрудников фирмы на 20%:

    UPDATE employers SET salary=salary*1.2

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

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

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

    В СУБД различных поставщиков начало транзакции может задаваться явно (например, командой BEGIN TRANSACTION), либо предполагаться неявным (так определено в стандарте SQL), т.е. очередная транзакция открывается автоматически сразу же после удачного или неудачного завершения предыдущей. Для завершения транзакции обычно используют команды SQL:

    • COMMIT'>COMMIT - успешно завершить транзакцию

    • ROLLBACK - откатить транзакцию, т.е. вернуть БД в состояние, в котором она находилась на момент начала транзакции.

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

    1. оператор COMMIT означает успешное завершение транзакции, все изменения, внесненные в базу данных делаются постоянными

    2. оператор ROLLBACK прерывает транзакцию и отменяет все внесенные ею изменения

    3. успешное заверешение программы, инициировавшей транзакцию, означает успешное завершение транзакции (как использование COMMIT)

    4. ошибочное завершение программы прерывает транзакцию (как ROLLBACK)

    Пример явно заданной транзакции:

    BEGIN TRANSACTION; /* Начать транзакцию */

    DELETE ...; /* Изменения */

    UPDATE ...; /* данных */

    if (обнаружена_ошибка) ROLLBACK;

    else COMMIT; /* Завершить транзакцию */

    Пример неявно заданной транзакции:

    СOMMIT; /* Окончание предыдущей транзакции */

    DELETE ...; /* Изменения */

    UPDATE ...; /* данных */

    if (обнаружена_ошибка) ROLLBACK;

    else COMMIT; /* Завершить транзакцию */

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

    • Грязное чтение (Dirty Read) - транзакция Т1 модифицировала некий элемент данных. После этого другая транзакция Т2 прочитала содержимое этого элемента данных до завершения транзакции Т1. Если Т1 заврешается операцией ROLLBACK, то получается, что транзакция Т2 прочитала не существующие данные.

    • Неповторяемое (размытое) чтение (Non-repeatable or Fuzzy Read) - транзакция Т1 прочитала содержимое элемента данных. После этого другая транзакция Т2 модифицировала или удалила этот элемент. Если Т1 прочитает содержимое этого элемента занова, то она получит другое значение или обнаружит, что элемент данных больше не существует.

    • Фантом (фиктивные элементы) (Phantom) - транзакция Т1 прочитала содержимое нескольких элементов данных, удовлетворяющих некому условию. После этого Т2 создала элемент данных, удовлетворяющий этому условию и зафиксировалась. Если Т1 повторит чтение с тем же условием, она получит другой набор данных.

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

    Все описанные выше ситуации возникли только потому, что чередующееся выполнение транзакций Т1 и Т2 не было упорядочено, т.е. не было эквивалентно выполнению сначала транзакции Т1, а затем Т2, либо, наоборот, сначала транзакции Т2, а затем Т1.

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

    • блокировка со взаимным доступом, называемая также S-блокировкой (от Shared locks) и блокировкой по чтению.

    • монопольная блокировка (без взаимного доступа), называемая также X-блокировкой от (eXclusive locks) или блокировкой по записи. Этот режим используется при операциях изменения, добавления и удаления объектов.

    При этом:

    • если транзакция налагает на объект X-блокировку, то любой запрос другой транзакции с блокировкой этого объекта будет отвергнут.

    • если транзакция налагает на объект S-блокировку, то

      • запрос со стороны другой транзакции с X-блокировокй на этот объект будет отвергнут

      • запрос со стороны другой транзакции с S-блокировокй этого объекта будет принят

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

    Доказано, что сериализуемость транзакций (или, иначе, их изоляция) обеспечивается при использовании двухфазного протокола блокировок (2LP - Two-Phase Locks), согласно которому все блокировки, произведенные транзакцией, снимаются только при ее завершении. Т.е выполение транзакции разбивается на две фазы: (1) - накопление блокировок, (2) - освобождение блокировок в результате фиксации или отката.

    К сожалению, применение механизма блокировки приводит к замедлению обработки транзакций, поскольку система вынуждена ожидать пока освободятся данные, захваченные конкурирующей транзакцией. Решить эту проблему можно за счет уменьшения фрагментов данных, захватываемых транзакцией. В зависимости от захватываемых объектов различают несколько уровней блокировки:

    • блокируется вся база данных - очевидно, этот вариант неприемлим, поскольку сводит многопользовательский режим работы к однопользовательскому

    • блокируются отдельные таблицы

    • блокируются страницы (страница - фрагмент таблицы размером обычно 2-4 Кб, единица выделения памяти для обработки данных системой)

    • блокируются записи

    • блокируются отдельные поля

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

    Язык SQL также предоставляет способ косвенного управления скоростью выполения транзакций с помощью указания уровня изоляции транзакции. Под уровнем изоляции транзакции понимается возможность возникновения одной из описанных выше ошибочных ситуаций. В стандарте SQL определены 4 уровня изоляции:

    Уровень изоляции

    Грязное чтение

    Размытое чтение

    Фантом

    Незафиксированное чтение
    (READ UNCOMMITTED)

    возможно

    возможно

    возможно

    Зафиксированное чтение
    (READ COMMITED)

    невозможно

    возможно

    возможно

    Повторяемое чтение
    (REPEATABLE READ)

    невозможно

    невозможно

    возможно

    Сериализуемость
    (SERIALIZABLE)

    невозможно

    невозможно

    невозможно

    Для определения характеристик транзакции используется оператор

    SET TRANSACTION <режим_доступа>, <уровень_изоляции>

    Список уровней изоляции приведен в таблице. Режим доступа по умолчанию используется READ WRITE (чтение запись), если задан уровень изоляции READ UNCOMMITED, то режим доступа должен быть READ ONLY (только чтение).

    Одним из наиболее серьезных недостатков метода сериализации транзакций на основе механизма блокировок является возможность возникновения тупиков (dead locks) между транзакциями. Пусть, например, транзакция Т1 наложила монопольную блокировку на объект О1 и претендует на доступ к объекту О2, который уже монопольно заблокирован транзакцией Т2, ожидающей доступа к объекту О1. В этом случае ни одна из транзакций продолжаться не может, следовательно, блокировки объектов О1 и О2 никогда не будут сняты. Естественного выхода из такой ситуации не существует, поэтому тупиковые ситуации обнаруживаются и устраняются искусственно. При этом СУБД откатывает одну из транзакций, попавших в тупик ("жертвует" ею), что дает возможность продолжить выполнение другой транзакции.

    Вопрос обеспечения параллельного выполнения транзакций весьма сложен и многие моменты остались за рамками данного раздела. Заинтересованный читатель может найти более полное изложение этой темы в одном из источников, указанных в списке литературы.
    1   ...   9   10   11   12   13   14   15   16   ...   23


    написать администратору сайта