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

Вид материалаДокументы

Содержание


Управление транзакциями и параллельным выполнением
Что такое транзакция?
За­прос к базе данных
Оценка результатов транзакции
Select accnum, acc_balance from снескасс
Update product
Update product
Свойства транзакции
Атомарность (atomicity)
Долговечность (durability)
Сериолызуемость (serializability)
Изолированность (isolation)
Управление транзакциями с помощью SQL
Update product
Begin transaction
Журнал транзакций
Таблица 9.1. Журнал транзакцш TRL TRX Пред. След. Операция Таблица Идент. Атрибут "до" "после"
Управление параллельным выполнением транзакций
Т1 prod_qoh = 35 + 100
1 Prod_qoh = 35 + 100
...
Полное содержание
Подобный материал:
1   ...   6   7   8   9   10   11   12   13   ...   23

Управление транзакциями и параллельным выполнением

  • В этой главе вы узнаете:
  • что такое транзакция базы данных и каковы ее свойства;
  • как управлять транзакциями в БД;
  • что такое управление параллельным выполнением транзакций и какова его роль в обеспечении целостности базы данных;
  • что собой представляют методы блокировки и как они работают;
  • как используется управление восстановлением базы данных для обеспечения це­лостности .

Обзор


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

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

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

Мы также покажем, что большинство алгоритмов управления параллельным выпол­нением используют блокировки, метки времени или оптимистические методы. По­скольку блокировки являются основой для большинства методов управления парал­лельным выполнением, мы исследуем различные уровни и типы блокировок. Так как блокировки могут стать причиной возникновения тупиков (deadlock), мы обсу­дим три стратегии контроля тупиков: выявление, предотвращение и устранение. За­тем мы обсудим результаты использования меток времени и оптимистических мето­дов в управлении параллельным выполнением.

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

Что такое транзакция?

Если вы читаете информацию из базы данных и/или записываете данные в БД (обновление), то вы порождаете транзакцию. Транзакция может состоять из про­стого оператора SELECT для вывода содержимого таблицы или из серий взаимосвя­занных командных последовательностей обновления (UPDATE). Например, если вы продаете товар клиенту, то ваша транзакция будет состоять, по крайней мере, из двух частей: вам необходимо обновить склад, уменьшив количество единиц товара в таблице PRODUCT (товар), вычтя из него количество проданных единиц, а также обновить таблицу счетов для того, чтобы затем выставить счет клиенту.

Большинство транзакций действующих БД состоят из двух или более запросов. За­прос к базе данных эквивалентен одному SQL-оператору в прикладной программе или транзакции. Таким образом, только что описанная транзакция покупки форми­руется их двух запросов к БД (два последовательных оператора UPDATE), каждый из которых обновляет базу данных. Каждый запрос к базе данных порождает не­сколько операций ввода/вывода (input/output, I/O).

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

На рис. 9.1 представлена типичная транзакция инвентарного учета, при которой происходит обновление базы данных уменьшением имеющихся в наличии товаров (40 единиц) на 10 единиц (проданное количество), при этом на складе остается 30 единиц. Транзакция, которая изменяет содержимое базы данных, переводит БД из одного устойчивого состояния (consistent state) в другое. Устойчивым состоянием

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



Рис. 9.1. Пример транзакции

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

Если в процессе транзакции получен доступ к БД, то после этого можно манипули­ровать ее содержимым. На примере рис. 9.1 элемент данных X должен быть считан из постоянного хранилища в оперативную память; его значение затем обновляется путем вычитания 10 единиц, и новое значение X записывается обратно из оператив­ной памяти в постоянное хранилище. Во время этой транзакции СУБД должна га­рантировать, что ни одна другая транзакция не получит доступа к объекту X. После завершения транзакции все использованные в ней данные высвобождаются, чтобы к ним можно было получить доступ из других транзакций. База данных возвращается в устойчивое состояние.

Оценка результатов транзакции

Предположим, что нам необходимо проверить текущий баланс счета № 0908110638, размещенного в таблице СНЕСКАСС. Такая транзакция может быть выполнена с помощью SQL-кода

SELECT ACCNUM, ACC_BALANCE FROM СНЕСКАСС

WHERE ACC_NUM = '0908110638';

Несмотря на то что мы не сделали никаких изменений в таблице СНЕСКАСС, SQL-код представляет собой транзакции, поскольку мы получали доступ к базе дан­ных. Если база данных находилась в устойчивом состоянии перед тем, как к ней был получен доступ, она останется в устойчивом состоянии и после этого, посколь­ку эта транзакция не изменяет содержимое БД.

Второй пример иллюстрирует более сложный набор транзакций. Предположим, что бухгалтеру необходимо оформить продажу в кредит 100 единиц товара X клиенту Y на сумму $500. Необходимые транзакции могут быть выполнены в следующей по­следовательности:
  • уменьшить количество товара X (quantity on hand, QOH) на 100;
  • добавить сумму $500 на дебиторский счет клиента Y.
    С помощью SQL мы можем написать:

UPDATE PRODUCT

SET PROD_QOH = PROD_QOH - 100

WHERE PROD_CODE = 'X'; UPDATE ACCT_RECEIVABLE

SET ACCT_BALANCE = ACCT_BALANCE + 500 WHERE ACCT_NUM = 'Y';

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

Теперь предположим, что СУБД завершила первую транзакцию, обновив количество товара X на складе. А во время выполнения второй части транзакции (обновление -UPDATE — таблицы дебиторских счетов) произошло отключение электропитания Если компьютер не оборудован устройством бесперебойного питания, вторая часть транзакции не будет завершена. Поэтому таблица PRODUCT перейдет в обновлен­ное состояние (соответствующим образом будет уменьшено количество товара на складе), но на дебиторский счет клиента сумма покупки не будет выставлена. База данных перейдет в неустойчивое состояние и не сможет корректно выполнять по­следующие транзакции. СУБД должна обеспечивать возможность восстановления базы данных в предыдущее устойчивое состояние.

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

UPDATE PRODUCT

SET PROD_QOH = PROD_QOH +10 WHERE PROD_CODE = 'X';



Продажа должна привести к уменьшению значения атрибута PROD_QOH (наличие това­ра) на 10. Вместо этого эта команда UPDATE добавляет 10 единиц к значению атрибута PROD_QOH.

Хотя синтаксис этой команды UPDATE правильный, она приведет к неверному результату. Тем не менее, в любом случае СУБД выполнит эту транзакцию. Для СУБД не имеет значения, верно ли отражает данная транзакция реальные операции — это задача конечного пользователя. Конечные пользователи и программисты могут со- вершить в этом случае множество ошибок. Представьте себе последствия уменьше­ния количества товара S на складе вместо того, чтобы уменьшить количество товара X или зачисления кредитной суммы на дебиторский счет клиенту U вместо клиента У(эти буквы находятся рядом на клавиатуре).

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


Свойства транзакции

Все транзакции должны обладать свойствами атомарности, сериализуемости, сериализуемости и изолированности. Мы кратко исследуем каждое из этих свойств.
  • Атомарность (atomicity) требует, чтобы все операции (части) транзакции были завершены. В противном случае транзакция отменяется. Другими словами, тран­закция представляет собой отдельную, неделимую логическую единицу работы.
  • Долговечность (durability) указывает на непрерывность устойчивого состояния БД. После завершения транзакции база данных должна переходить в устойчивое со­стояние и это состояние не должно нарушаться даже при сбоях системы.
  • Сериолызуемость (serializability) представляет собой возможность одновременного выполнения нескольких транзакций. Точнее, под одновременными транзакциями понимается их сериализованное, последовательное выполнение (одна за другой). Это свойство имеет большое значение в многопользовательских и распре­деленных базах данных, где несколько транзакций с большой долей вероятности могут выполняться параллельно.
  • Изолированность (isolation) означает, что данные, использующиеся в одной тран­закции, не могут ислользоваться другой транзакцией до тех пор, пока первая не будет завершена. Другими словами, если выполняется транзакция Т1 и использу­ет объект данных X, то этот объект данных не может быть доступен никакой другой транзакции (Т2, ..., Тя) до завершения транзакции Т1. Это свойство имеет практическое значение в многопользовательских базах данных, поскольку здесь несколько пользователей одновременно могут получать доступ к базе данных.

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

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


Управление транзакциями с помощью SQL

Национальный Институт Стандартизации США (The American National Standards Institute, ANSI) устанавливает стандарты, определяющие управление транзакциями база данных с помощью SQL. Поддержка транзакций обеспечивается двумя SQL-операторами: COMMIT и ROOLBACK. Стандарты ANSI требуют, чтобы после ини­циализации транзакции пользователем или прикладной программой она выполня­лась последовательностью SQL-операторов, пока не произойдет одно из следующих четырех событий:
  1. Достигнут оператор COMMIT. В этом случае все изменения записываются в БД.
    Оператор COMMIT автоматически завершает SQL-транзакцию.
  2. Достигнут оператор ROLLBACK. В этом случае все изменения отменяются, и
    база данных возвращается в предыдущее устойчивое состояние.
  3. Достигнут конец программы. В этом случае все изменения записываются в базу
    данных для постоянного хранения. Это событие эквивалентно выполнению опе­ратора COMMIT.
  4. Выполнение программы неожиданно прервано. В этом случае все изменения
    отменяются, и база данных возвращается в предыдущее устойчивое состояние.
    Это событие эквивалентно выполнению оператора ROLLBACK.

Применение оператора COMMIT иллюстрируется следующими операциями прода­жи, при которых обновляется количество товара на складе (таблица PROD_QOH) и на дебиторский счет клиента записывается $3500 при покупке клиентом 100 единиц товара 345TYX:

UPDATE PRODUCT

SET PROD_QOH = PROD_QOH - 100 WHERE PROD_CODE = '345TYX1;


Update acct_receivable

set acct_balance = acct_balance + 3500 where acct_num = '60120010';

COMMIT;

На самом деле оператор COMMIT, использованный в данном примере, необязателен, если оператор UPDATE является последним действием приложения и приложение завершается нормальным образом.

Транзакция начинает выполняться явно, как только встретится первый SQL- оператор. Не все реализации SQL соответствуют стандартам ANSI. В некоторых версиях используются операторы управления транзакциями, например, оператор

BEGIN TRANSACTION;

указывает начало новой транзакции. В других реализациях SQL, например, VAX/SQL, разрешается присваивать свойства транзакциям в качестве параметров оператора BEGIN.

Журнал транзакций

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

Когда СУБД выполняет транзакции, вызывающие изменения в БД, происходит ав­томатическое обновление журнала транзакций. В журнале хранится следующая ин­формация:
  • запись о начале транзакции;
  • для каждого компонента транзакции (SQL-оператора) хранятся:
  • тип выполняемой операции (обновление, удаление, вставка);
  • имена объектов, на которые влияет транзакция (названия таблиц);
  • значения "до" и "после" для обновляемых полей;
  • указатели на предыдущую и последующие записи для такой же транзакции;

завершение транзакции (COMMIT).

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

В табл. 9.1 представлен упрощенный вид журнала транзакций, где отражены пред­ставленные выше два SQL-оператора UPDATE. В случае системного сбоя СУБД обращается к журналу транзакций для поиска всех незавершенных или не полно­стью завершенных транзакций и на основе этой информации осуществляет откат (ROLLBACK) базы данных к предыдущему состоянию. После завершения процесс восстановления СУБД записывает в журнал все завершенные транзакции, которые; не были записаны в базу данных перед возникновением сбоя.

Таблица 9.1. Журнал транзакцш

TRL TRX Пред. След. Операция Таблица Идент. Атрибут "до" "после"

ID NUM PTR PTR столбца

341 101 Null 352 START *** Start

Transaction

352 101 341 363 UPDATE PRODUCT 345TYX PROD_QOH 243 143

363 101 352 365 UPDATE ACCT_ 60120010 ACCT_BALANCE 1200 4700

RECEIVABLE

365 101 363 Null COMMIT *** End

transaction

Примечание:

TRL ID = идентификатор записи в журнале транзакций

TRX NUM = номер транзакции

PTR = указатель идентификатора записи в журнале транзакций

(Номер транзакции TRX NUM автоматически присваивается СУБД).

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

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


Управление параллельным выполнением транзакций

Управление параллельным выполнением транзакций это координирование одновре­менного исполнения транзакций в распределенных базах данных. Цель управления параллельным выполнением состоит в обеспечении сериализации транзакций в многопользовательских базах данных. Контроль параллельного выполнения очень важен, поскольку одновременное выполнение транзакций в распределенных базах данных может стать причиной проблем с целостностью и непротиворечивостью данных. Тремя основными проблемами можно считать потерю изменений (lost up­date), несвязность данных (uncommited data) и неоднозначность поиска (inconsistent retrievals).

Потеря изменений
  • Для иллюстрации потери изменений исследуем простую таблицу PRODUCT (товар).
  • Одним из атрибутов этой таблицы является количество товара на складе
  • (PRODQOH). Предположим, что у нас есть товар, количество которого в настоя­вший момент (PRODQOH) равно 35. Пусть имеют место две параллельные транзакции Т1 и Т2, которые вызывают обновление значения PROD_QOH для некоторых
    I объектов таблицы PRODUCT. Эти транзакции выглядят так:

Транзакция Вычисление

Т1: Покупка 100 единиц → PROD_QOH = PROD_QOH + 100 IT2: Т2: Продажа 30 единиц → PROD_QOH = PROD_QOH - 30

В табл. 9.2 представлено последовательное выполнение этих транзакций в нормальных условиях, которое дает правильный результат PROD_QOH = 105.

Таблица 9.2. Нормальное выполнение двух транзакций

Время Транзакция Шаг Хранимое значение
  1. Т1 Чтение PROD_QOH 35
  2. Т1 PROD_QOH = 35 + 100
  3. Т1 Запись PROD_QOH 135
  4. Т2 Чтение PROD_QOH 135
  5. Т2 PROD_QOH = 135-30
  6. Т2 Запись PROD_QOH 105

Но представим себе, что транзакции могут считывать значение PROD_QOH из таб­лицы до завершения предыдущей транзакции (использующей mom же товар). По­следовательность операций, представленная в табл. 9.3, показывает, как возникает проблема потери изменений. Обратите внимание, что первая транзакция (Т1) еще не завершилась, когда уже выполняется вторая транзакция (Т2). Поэтому Т2 все еще оперирует со значением 35 и уменьшение этого значения на 30 дает результат 5, хранящийся в оперативной памяти. Тем временем Т1 записывает значение 135 на диск, которое тут же переписывается значением 5 транзакции Т2. Короче говоря, добавление 100 единиц "теряется" при такой последовательности операций.

Таблица 9.3. Потеря изменений

Время Транзакция Шаг Хранимое значение
  1. Т1 Чтение PROD_QOH 35
  2. Т2 Чтение PROD_QOH 35
  3. Т 1 PROD_QOH = 35 + 100

Таблица 9.5. Проблема несвязности данных

Время Транзакция Шаг Хранимое значение

1 Т1 Чтение PROD_QOH 35

2 Т1 PROD_QOH = 35 + 100

3 Т1 Запись PROD_QOH 135

4 Т2 Чтение PROD_QOH (чтение 135

несвязанных данных)
  1. Т2 PROD_QOH=135-30
  2. Т1 ***** ROLLBACK ***** 35
  3. Т2 Запись PROD_QOH 105




Неоднозначность поиска

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

Для иллюстрации такой проблемы представим следующий сценарий.
  1. В транзакции Т1 рассчитывается общее количество товара в таблице PRODUCT.
  2. Одновременно транзакция Т2 обновляет количество (PROD_QOH) для двух то­
    варов в таблице PRODUCT.

Эти две транзакции представлены в табл. 9.6.

Таблица 9.6. Поиск данных во время обновления

Транзакция Т1 Транзакция Т2

S ELECT SUM (PROD_QOH) UPDATE PRODUCT

FROM PRODUCT SET PROD_QOH = PROD_QOH +30

WHERE PROD_CODE = 425TYZ' UPDATE PRODUCT

SET PROD_QOH = PROD_QOH - 30 WHERE PRODJCODE = '34 5TYZ1 COMMIT;

Пока Tl рассчитывает общее количество товара (PRODQOH) по всем позициям, тран­закция Т2 производит коррекцию ошибок ввода: пользователь добавил 30 единиц товара

345TYX (PROD_QOH) вместо добавления 30 единиц товара 125TYZ (PROD_Q0Н) Начальное и конечное значения PRODQOH представлены в табл. 9.7

Таблица 9.7. Результаты транзакций: исправление введенных данных



Хотя окончательные результаты после исправлений правильные, в табл. 9.8 проде­монстрировано, что во время выполнения транзакций возможен неоднозначна поиск, что делает результаты транзакции Т1 неверными.