РУКОВОДСТВО ПО РЕЛЯЦИОННОЙ СУБД DB2

ЧТО ТАКОЕ ТРАНЗАКЦИЯ


Транзакция в том смысле, в котором мы используем этот термин,— это логическая единица работы. Рассмотрим следующий пример (обобщенный вариант примера 6.2.4 из главы 6, представленный в форме встроенного SQL): заменить номер 'Sx' поставщика на 'Sy', где Sx и Sy — параметры. Для простоты опустим ряд проверок достоверности данных, которые обычно включаются в реальную программу. Кроме того, опустим все объявления.

TRANEX: PROC OPTIONS (MAIN);      /* пример транзакции */

EXEC SQL      WHENEVER SQLERROR GO TO UNDO;

GET LIST        (SX, SY);

EXEC SQL      UPDATE         S

                        SET                  НОМЕР_ПОСТАВЩИКА = :SY

WHERE           НОМЕР_ПОСТАВЩИКА = :SX;

EXEC SQL      UPDATE         SP

                        SET                  НОМЕР_ПОСТАВЩИКА == :SY

                        WHERE           НОМЕР_ПОСТАВЩИКА = :SX;

EXEC SQL      COMMIT;

GO TO FINISH;

UNDO:     EXEC SQL ROLLBACK;

FINISH:    RETURN;

END TRANEX;

Смысл данного примера заключается в том, что выражение «Заменить номер поставщика Sx на Sy», воспринимаемое конечным пользователем, вероятно, как единственная атомарная операция, требует на самом деле двух операций UPDATE над базой данных. Более того, между этими двумя операциями может даже нарушаться непротиворечивость базы данных. Например, в ней могут временно содержаться некоторые записи поставок, для которых не имеется соответствующих записей поставщиков. Заметим, что это наблюдение остается в силе, если изменить порядок исполнения двух операций UPDATE в приведенном примере. Таким образом, транзакция или логическая единица работы — не обязательно только одна операция языка SQL. В общем случае это, скорее, последовательность

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

Ясно теперь, что в данном примере не следует допускать таких случаев, когда одна из двух операций


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

Администратор транзакций — это системный компонент, который обеспечивает такую атомарность или подобие атомарности, а операции COMMIT (фиксировать) и ROLLBACK (откат) полностью определяют способ его функционирования. Операция COMMIT сигнализирует об успешном завершении транзакции. Она сообщает администратору транзакций, что логическая единица работы была успешно завершена, что база данных снова находится (или должна находиться) в непротиворечивом состоянии, и все произведенные этой единицей работы обновления могут быть теперь «зафиксированы», т. е. приняты за свершившиеся. Напротив, команда ROLLBACK сигнализирует о неудачном завершении транзакции. Она сообщает администратору транзакций, что что-то испортилось, что непротиворечивое состояние базы данных, возможно, нарушено и что для всех произведенных до сих пор данной логической единицей работы обновлений следует сделать «откат», т. е. аннулировать их. Под «обновлением» здесь понимаются, конечно, операции INSERT и DELETE, а также сами по себе операции UPDATE.



В приведенном примере команда COMMIT издается, следовательно, в том случае, если успешно проведены обе операции UPDATE, в результате чего изменения будут фиксироваться в базе данных и принимаются за свершившиеся. Если, однако, что-нибудь испортится, т. е. для какой-либо из операций UPDATE возвращаемое значение SQLCODE будет отрицательным, то вместо этого издается ROLLBACK с тем, чтобы аннулировать сделанные до сих пор изменения. В приведенном примере операции COMMIT и ROLLBACK издаются явным образом. Однако, как указывалось в конце главы 10, для любой исполняемой в обстановке системы DB2 программы при ее нормальном завершении будет автоматически издаваться COMMIT. В противном случае для нее автоматически будет издаваться ROLLBACK, независимо от причины аварийного завершения программы. Если, в частности, программа аварийно завершается в связи со сбоем системы, ROLLBACK издается от имени этой программы при рестарте системы. Следовательно, в приведенном примере можно было бы опустить явно специфицированное предложение COMMIT, но не следует опускать явного предложения ROLLBACK.

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

Отметим в заключение еще один момент. Как уже было указано в главе 1, предложения манипулирования данными языка SQL относятся к уровню множеств, и обычно операция осуществляется одновременно над множеством записей. Что же тогда произойдет, если возникнет какая-либо ошибка во время исполнения такого предложения? Возможно ли, например, чтобы вторая операция UPDATE в приведенном примере обновила бы некоторые из ее целевых записей в таблице SP, а затем неудачно завершилась, не осуществив обновления остальных записей этой таблицы? Ответ отрицателен, это невозможно. Система DB2 гарантирует, что все предложения языка SQL в отдельности являются атомарными, по крайней мере, в отношении их влияния на базу данных. Если во время исполнения такого предложения все же имела место ошибка, то база данных останется полностью неизменной.


Содержание раздела