Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Лекция 5 - Введение в транзакции.doc
Скачиваний:
0
Добавлен:
01.05.2025
Размер:
357.38 Кб
Скачать

Часть 2. Управление транзакциями

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

Прежде всего, имеется в виду выполнение операторов

  1. INSERT,

  2. UPDATE,

  3. DELETE.

Например, после создания таблицы (выпол­нения оператора CREATE TABLE) не нужно фиксировать результат, поскольку созда­ние таблицы фиксируется в базе данных автоматически.

Или, например, с по­мощью команды отмены транзакции не удастся восстановить только что удаленную оператором DROP TABLE таблицу.

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

После завершения транзакции вся информация о произведенных изменениях хранится либо в специально выделенной оперативной памяти, либо во временной области отката в самой базе данных до тех пор, пока не будет выполнена одна из команд управления транзакциями:

COMMIT - для сохранения изменений;

ROLLBACK - для отмены изменений;

SAVEPOINT - для установки особых точек возврата.

Тогда все из­менения или фиксируются в базе данных, или отбрасываются и временная область отката освобождается.

Команда COMMIT предназначена для сохранения в базе данных всех изменений, произошедших в ходе выполнения транзакции. Она сохраняет результаты всех операций, которые имели место после выполнения пос­ледней команды COMMIT или ROLLBACK.

Команда ROLLBACK предназначена для отмены транзакций, еще не сохраненных в базе данных. Она отменит только те транзакции, которые начались с момента выполнения последней команды COMMIT или ROLLBACK.

Команда SAVEPOINT (точка сохранения) предназначена для уста­новки в транзакции особых точек, до которых в дальнейшем может быть произ­веден откат (при этом отката всей транзакции не происходит).

Команда имеет следующий вид:

SAVEPOINT [имя_точки_сохранения | @переменная точки сохранения]

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

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

Для отмены действия группы транзакций, ограниченных точками со­хранения, используется команда ROLLBACK со следующим синтаксисом:

ROLLBACK TO [имя_точки_сохранения | @переменная точки сохранения]

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

Пример 1.

BEGIN TRAN

IF (SELECT COUNT(Поставки.Количество_ед_товара)

FROM Товары INNER JOIN Поставки

ON Товары. ID_товара = Поставки.Товар

WHERE Товары.Название_товара = ‘Кофе Ирландский крем’) >=400

BEGIN

ROLLBACK TRAN

RETURN

END

UPDATE Продажи

SET Цена_ед_товара = Цена_ед_товара + 500

FROM Товары INNER JOIN Продажи

ON Товары. ID_товара = Продажи.Товар

WHERE Товары.Название_товара = ‘Кофе Ирландский крем’

-- анализ кода ошибки производится при обновлении таблицы

IF @@error <>0

BEGIN

ROLLBACK TRAN

RETURN

END

COMMIT TRAN

В этом примере команда begin tran сообщает серверу о начале транзакции. Это означает, что до получения сервером команды завершения транзакции (commit tran) все изменения являются временными. Следовательно, если на сервере произойдет сбой после первого обновления, выполнится откат транзакции.

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

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

Термин "блокировка" (lock) означает, что никакой процесс не сможет обратиться к данным до их освобождения (посредством закрепления или отката транзакции). Только процесс, являющийся владельцем блокировки, сможет просмотреть заблоки­рованные данные.

Если во время транзакции произойдут ошибки (или если этого требует логи­ка программы), выполняется команда rollback tran.

Команды управления транзакциями не влияют на последовательность вы­полнения программы.

Примечание

Команда rollback tran не влияет на последовательность выполнения ко­манд программы. Следовательно, после отката необходимо выполнить коман­ду RETURN.

Пример 2. В этом примере иллюстрируется последова­тельность выполнения транзакций.

BEGIN TRAN Tr1

INSERT MyTable VALUES (1)

PRINT @@TRANCOUNT -- значение = 1

SAVE TRAN Point_1

INSERT MyTable VALUES (2) -- здесь может быть любой SQL-код

--Откат к точке Point_1, если возникла ошибка

IF @@error <> 0

ROLLBACK TRAN Point_1

ELSE

IF (SELECT COUNT(*) FROM MyTable) > 3

-- если меньше количество записей >3, произойдет откат к началу транзакции

ROLLBACK TRAN Tr1

INSERT MyTable VALUES (3) -- здесь может быть любой SQL-код

-- Откат к началу транзакции, если была хоть одна ошибка

IF @@error <> 0

ROLLBACK TRAN Tr1

COMMIT TRAN Tr1

Здесь после открытия транзакции добавляется запись в таблицу MyTable. Эта добав­ленная запись уже находится в таблице, но может участвовать в запросах только со сторо­ны процесса, открывшего транзакцию. Она будет недоступна со стороны всех остальных процессов до закрепления транзакции.

Команда save tran используется в качестве "закладки". Она не влияет на значение @@trancount и не изменяет уровня вложенности транзакции, она лишь позволяет позднее вернуть транзакцию к этой точке.

Сервер запоминает факт начала транзакции, обновляя глобальную перемен­ную @@trancount.

Вначале переменная @@trancount равна 0. Она увеличива­ется на 1 для каждой новой вложенной транзакции.

Управление транзакциями в среде MS SQL Server

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

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

Пользователи в основном должны указывать только начало и конец транзакции, используя команды SQL или API (прикладного интерфейса программирования).

Если пользователь попытается установить соединение снова и продолжить выполнение транзакции, то это не удастся.

SQL Server поддерживает три вида определения транзакций:

• автоматическое;

• явное;

• неявное (подразумеваемое).

По умолчанию SQL Server работает в режиме автоматического нача­ла транзакций, когда каждая команда рассматривается как отдельная транзакция.

При этом если отдельная команда выполнена успешно, то ее изменения фикси­руются. Если при выполнении команды произошла ошибка, то сделан­ные изменения отменяются и система возвращается в первоначальное состояние.

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

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

Установка режима явного опре­деления транзакций выполняется посредством другой команды:

SET IMPLICIT_TRANSACTIONS ON

Для установки режима автоматического определения транзакций отключается режим явного определения транзакций - используется команда:

SET IMPLICIT_TRANSACTIONS OFF

Явные транзакции

Явные транзакции требуют, чтобы пользователь указал начало и ко­нец транзакции, используя следующие команды:

  • Начало транзакции определяется командой

BEGIN TRAN [SACTION] [имя_транзакции | @имя_переменной_транзакции ]

[WITH MARK ['описание_транзакции']]

При этом в журнале транзакций фиксируется момент начала транзакции и первона­чальные значения данных;

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

COMMIT [TRANSACTION] [имя_транзакции | @имя_переменной_транзакции]

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

SAVE TRAN [ SACTION ] [имя_точки_сохранения | @имя_переменной_точки_сохранения]

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

ROLLBACK [TRAN [ SACTION ]] [имя_транзакции | @имя_

переменной_транзакции | имя_точки__сохранеия | @имя_переменной_точки_сохранения]

Эта команда либо отменяет все изменения, сделанные в БД после оператора BEGIN TRANSACTION, либо отменяет изменения, сделанные в БД после точки сохранения, возвращая транзакцию к месту, где был выполнен оператор SAVE TRANSACTION.

Некоторые полезные функции:

Функция @@TRANCOUNT возвращает количество активных транзакций.

Функция @@NESTLEVEL возвращает уровень вложенности транзакций.

Пример 3. Использование точек сохранения.

Пусть применительно к таблице Товар выполняются следующие команды:

BEGIN TRAN

SAVE TRAN point1

При этом в точке point 1 сохраняется первоначальное состояние таблицы Товар

DELETE FROM Товар WHERE ID_Товара=2

SAVE TRAN point2

В точке point2 сохраняется состояние таблицы Товар без товара с кодом 2.

DELETE FROM Товар WHERE ID_Товара=3

SAVE TRAN point3

В точке point3 сохраняется состояние таблицы Товар без двух товаров - с кодом 2 и с кодом 3.

DELETE FROM Товар WHERE ID_Товара<>1

ROLLBACK TRAN point3

Сначала удаляются все записи кроме одной – с ID_Товара<>1. Но потом происходит отмена удаления и возврат в состояние таблицы без товаров с кодами 2 и 3.

SELECT * FROM Товар

Оператор SELECT покажет таблицу товар без товаров с кодами 2 и 3.

ROLLBACK TRAN point1

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

SELECT * FROM Товар

COMMIT

При этом сохраняется первоначальное состояние таблицы.

в) Вложенные транзакции

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

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

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

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

Только когда все транзакции на всех уров­нях завершены успешно, происходит фиксация всех сделанных изменений.

Каждая команда COMMIT TRANSACTION работает только с последней начатой транзакцией. Да­же если в команде COMMIT TRANSACTION указано имя транзакции более высокого уровня, будет завершена транзакция, начатая последней.

Если команда ROLLBACK TRANSACTION используется (на любом уровне вложенности) без указания имени транзакции, то откатываются все вложенные транзакции, включая транзакцию самого высокого (верх­него) уровня.

В команде ROLLBACK TRANSACTION разрешается указывать только имя самой верхней транзакции. Имена любых вложенных тран­закций игнорируются, и попытка их указания приведет к ошибке.

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

Если же требуется откатить лишь часть транзакций, можно использовать команду SAVE TRANSACTION, с помо­щью которой создается точка сохранения.

Пример 2. Использование вложенных транзакций

BEGIN TRAN

INSERT Товар (Название_товара, категория) VALUES ('кефир’,40)

BEGIN TRAN

INSERT Товар (Название_товара, категория) VALUES ('ряженка', 40)

BEGIN TRAN

INSERT Товар (Название_товара, категория) VALUES {'йогурт', 40)

ROLLBACK TRAN

Здесь происходит возврат на начальное состояние таблицы, посколь­ку выполнение команды ROLLBACK TRAN без указания имени транзакции откатывает все транзакции.