Главная » SQL, Базы данных » Транзакция как  логическая единица работы

0

Транзакция — это логическая единица работы; она начинается с выполнения операции BEGIN TRANSACTION и заканчивается операцией COMMIT или ROLLBACK. На рис. 15.1 показан псевдокод транзакции, которая предназначена для перечисления суммы 100 долл. со счета 123 на счет 456. Вполне очевидно, что операция перевода денег с одного счета на другой, которая по самой своей сути является неразрывной, фактически требует выполнения в базе данных двух отдельных операций обновления. Более того, сама база данных на этапе между этими двумя обновлениями находится в недопустимом состоянии, в том смысле, что она не отражает действительное состояние дел в реальном мире; вполне очевидно, что в банковской практике перевод денег с одного счета на другой не должен влиять на суммарное количество денежных средств на рассматриваемых счетах, а в данном примере после выполнения первого обновления сумма в 100 долл. на время "исчезает" из

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

Рис. 15.1. Пример транзакции (псевдокод)

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

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

1 Аварийный останов системы, который прерывает выполнение всех транзакций, действующих в системе во время его возникновения, называется также глобальным отказом или отказом системы, а отказ, такой как арифметическое переполнение, который влияет только на одну транзакцию, называется локальным отказом. Дополнительная информация на эту тему приведена, соответственно, в разделах 15 . 4  и  15. 3.

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

■   Оператор COMMIT (Зафиксировать) сигнализирует об успешном окончании  транзакции.  Он  сообщает  диспетчеру  транзакций,  что  логическая  единица  работы успешно завершена, база данных вновь находится (или  будет находиться после выполнения этого оператора) в непротиворечивом  состоянии, а все обновления, выполненные данной логической единицей работы, теперь могут быть зафиксированы, т.е. внесены в базу данных.

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

Таким образом, в приведенном примере оператор COMMIT должен быть выполнен, если оба  обновления  прошли  успешно,  после  чего  внесенные  в  базу  данных  изменения станут постоянными. Если что-то произошло не так, например, если  обновление было прервано каким-либо условием ошибки, то выполняется  оператор ROLLBACK И любые проведенные до сих пор изменения отменяются.

На основании простого примера, приведенного на рис. 15.1, можно сделать ряд важных выводов, описанных ниже.

■     Неявно заданный оператор ROLLBACK. В данном примере явно предусмотрено вы полнение проверок на наличие ошибок и явный вызов на выполнение оператора ROLLBACK в случае обнаружения ошибки. Но не следует предполагать (и само это предположение не имеет смысла), что транзакции всегда включают явно заданные проверки на случай всех возможных ошибок. Поэтому система должна вызывать на выполнение неявно заданный оператор ROLLBACK ДЛЯ всех транзакций, кото рые по какой-то причине окончились неудачей и не достигли этапа планового за вершения (здесь под плановым завершением подразумевается явно заданный опера торCOMMITИЛИROLLBACK).

■     Обработка сообщений. Типичная транзакция не только вносит (или пытается вне сти) обновления в базу данных, но и передает конечному пользователю те или иные сообщения, позволяющие ему узнать, что происходит. Например, можно предусмотреть передачу сообщения "Перевод денег со счета на счет выполнен", если достигнут оператор COMMIT, или сообщение "Ошибка — перевод денег со счета на счет не выполнен" в противном случае. Обработка сообщений, в свою очередь, требует применения дополнительных средств восстановления. Более под робную информацию по этой теме можно найти в [15.12].

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

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

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

■     Неразрывность операций. Система должна гарантировать, что выполнение отдель ных операций (весь процесс их выполнения) должно происходить неразрывно. Такое требование становится особенно важным в реляционных системах, по скольку в них операции выполняются на уровне множества и обычно затрагивают одновременно большое количество кортежей, поэтому нельзя допустить, чтобы такие операции оканчивались неудачей в ходе выполнения и оставляли базу дан ных в противоречивом состоянии (например, в таком состоянии, что некоторые кортежи обновлены, а другие — нет). Иными словами, если в ходе выполнения подобного оператора возникла ошибка, то база данных должна остаться полно стью в неизменном состоянии. Кроме того, как описано в главах 9 и 10, это условие остается в силе, даже если рассматриваемая операция неявно требует выполнения дополнительных обновлений (например, из-за того, что применяется правило каскадного удаления или происходит обновление представления, в котором пре дусмотрено соединение таблиц).

■     Выполнение программы как последовательности транзакций. Необходимо обратить особое внимание на то, что операторы COMMIT и ROLLBACK завершают транзак цию, а не прикладную программу. Как правило, процесс прогона отдельной про граммы состоит из ряда транзакций, которые следуют одна за другой, как показа но на рис. 15.2.

■     Отсутствие вложенных транзакций. Если явно не указано иное, то в данной главе предполагается, что в прикладной программе оператор BEGIN TRANSACTION мо жет быть вызван на выполнение, только если в настоящее время в этой программе не выполняется какая-либо другая транзакция. Иными словами, транзакция не может содержать в себе вложенную транзакцию. Но необходимо отметить, что в следующей главе это предположение будет пересмотрено.

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

непротиворечивости недостаточно; база данных должна отвечать требованиям допустимости, а не только непротиворечивости! Например, в случае транзакции, показанной на рис. 15.1, требуется, чтобы суммарное количество денег на счетах 123 и 456 в результате транзакции не изменилось. Но было бы неразумно ставить перед собой задачу по подготовке ограничения целостности, которое соответствовало бы такому требованию (объясните, почему), и поэтому нельзя рассчитывать на то, что СУБД сможет следить за соблюдением данного требования. В действительности, как уже было  сказано в главе 9, непротиворечивость не подразумевает правильность. Поэтому, к сожалению, все, что мы можем сделать (и чего мы вообще можем добиться с помощью СУБД), это просто принять предположение, что транзакции являются правильными, в том смысле, что они достоверно отражают лишь те операции реального мира, которые были реализованы с их помощью. Точнее, мы предполагаем, что если т — транзакция, которая  переводит базу данных из состояния D1 в состояние D2 и состояние D1 является правильным, то D2 также является правильным2. Но еще раз отметим, что это желаемое свойство не может быть обеспечено самой системой (как было указано в главе 9, система может обеспечить не истинность, а только непротиворечивость).

Рис. 15.2. Диаграмма, на которой процесс выполнения программы показан как ряд транзакций

■  Множественное присваивание. Как было указано в главе 5 (в соответствии с доводами, приведенными в [3.3]), в базе данных необходимо предусмотреть поддержку множественной формы присваивания, которая позволяет  выполнять одновременно любое количество отдельных операций присваивания (т.е. обновлений). Например, две отдельные операции UPDATE, показанные на рис. 15.1, могут быть заменены следующим одним  оператором (обратите внимание на применяемый в нем разделитель в виде запятой).

2 Следует также обратить особое внимание на то, что это утверждение должно распространяться на все возможные правильные состояния D1. Очевидно, что транзакция Т может фактически не "достоверно  отражать лишь те операции реального мира, которые были с помощью нее реализованы", и вместе с тем  обеспечивать переход в правильное состояние D2 из некоторого конкретного состояния D1. Но нас это не  вполне устраивает, поскольку правильность транзакции должна быть гарантированной, а не являться  просто  результатом случайного стечения обстоятельств.

UPDATE ACC 123 { BALANCE := BALANCE $100

} , UPDATE ACC 456 { BALANCE := BALANCE +

$100 } ;

Теперь эта транзакция будет включать только одну операцию обновления, поэтому ее воздействие на базу данных будет неразрывным по определению и  операторы BEGIN TRANSACTION, COMMIT и ROLLBACK больше не потребуются (по крайней мере, в данном конкретном случае). Но, как было отмечено в главе 5, современные программные продукты не поддерживают множественное присваивание (или поддерживают эту операцию не полностью). Поэтому по  практическим соображениям до конца данной главы возможность применения множественного присваивания не рассматривается. (Безусловно, при проведении  оригинальной исследовательской работы, посвященной транзакциям, возможность применения множественного присваивания фактически даже не рассматривалась. Дополнительная информация на эту тему приведена в разделе 16.10.)

Источник: Дейт К. Дж., Введение в системы баз данных, 8-е издание.: Пер. с англ. — М.: Издательский дом «Вильямс», 2005. — 1328 с.: ил. — Парал. тит. англ.

По теме:

  • Комментарии