Распечатать страницу

Транзакции в Microsoft Visual FoxPro

« Назад

Транзакция – это сохраняемые в оперативной памяти изменения таблиц базы данных. При завершении транзакции (команда END TRANSACTION) изменения переносятся на диск, то есть фиксируются в таблицах, участвующих в транзакции. Если в процессе транзакции обнаружена ошибка, то исходные значения в буфере восстанавливаются командой ROLLBACK. Эта же команда и завершает неудавшуюся транзакцию.

Команда

BEGIN TRANSACTION

начинает транзакцию. Транзакции поддерживаются для таблиц, входящих в базу данных. Для свободных таблиц и курсоров транзакции станут возможными после успешного употребления функции MAKETRANSACTABLE( ).

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

Число вложений транзакций – 5. При превышении этой цифры будет сгенерирована ошибка.

Продолжительность транзакции следует минимизировать или выполнять ее, когда другие пользователи не нуждаются в доступе к таблицам: записи, участвующие в транзакции, недоступны (для модификации и чтения) другим сетевым пользователям до ее завершения. При попытке получить доступ к такой записи пользователь будет наблюдать сообщение "Record not available ... please wait" до тех пор, пока запись не освободится.

Все индексные IDX-файлы и независимые CDX-файлы во время транзакции не должны быть открыты. Открытыми могут быть только структурные CDX-файлы.

Во время транзакции не поддерживаются следующие команды и функция:

ADD TABLE

APPEND PROCEDURES

CLEAR ALL

CLOSE ALL*

CLOSE DATABASES*

COPY INDEXES

COPY PROCEDURES

CREATE CONNECTION

CREATE DATABASE

CREATE TRIGGER

CREATE VIEW

CREATE SQL VIEW

DELETE CONNECTION

DELETE DATABASE

DELETE TRIGGER

DELETE VIEW

MODIFY CONNECTION

MODIFY DATABASE

MODIFY PROCEDURE

MODIFY VIEW

REMOVE TABLE

RENAME TABLE

REQUERY( )

 

* Если CLOSE ALL выполнить во время транзакции, то все отрытые таблицы закроются, но базы данных останутся открытыми. Выполнение CLOSE DATABASES во время транзакции закрывает все таблицы текущей базы данных, но не саму базу данных.

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

ALTER TABLE

CREATE TABLE

CURSORSETPROP( )

DELETE TAG

INDEX

INSERT

MODIFY STRUCTURE

PACK

REINDEX

TABLEREVERT( )

ZAP

 

Пример 1. Команды BEGIN TRANSACTION и ROLLBACK в таблице с буферизацией.

close databases

open database d:\HomeLibrary\HomeLibrary.dbc

use Authors

select Authors

&&

&& При использовании буферизации
&& SET MULTILOCKS нужно установить в ON

set multilocks on

&&

&& Активизируем буферизацию таблицы

CursorSetProp('Buffering', 5, 'Authors')

&&

&& Изменяем значения поля Author во всех записях таблицы

replace all Author with Upper(Author)

begin transaction

         && Фиксируем изменения

         TableUpdate(1)

         browse last && Наблюдаем преобразованную таблицу

&&

&& Отменяем изменения, выполненные во время транзакции

rollBack

browse last && Наблюдаем преобразованную таблицу

&& Восстанавливаем представление данных в буфере

TableRevert(.T.)

browse last && Наблюдаем исходную таблицу

В приведенном коде, поскольку используется буферизация, присутствие END TRANSACTION после ROLLBACK недопустимо.

Пример 2. Команды BEGIN TRANSACTION и ROLLBACK при отсутствии буферизации.

close databases

open database d:\HomeLibrary\HomeLibrary.dbc

use Authors

select Authors

begin transaction && Начинаем транзакцию

         replace all Author with Upper(Author)

         browse last && Наблюдаем преобразованную таблицу

&& Отказываемся от преобразований и завершаем транзакцию

rollback

browse last                          && Наблюдаем исходную таблицу

Команда

END TRANSACTION

завершает текущую транзакцию и сохраняет все изменения таблиц, их memo-файлов и индексов, выполненные во время транзакции.

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

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

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

Перед вызовом END TRANSACTION должна быть выполнена команда BEGIN TRANSACTION.

Если используется буферизация и выполнена команда ROLLBACK, то при последующем обращении к END TRANSACTION генерируется ошибка.

Пример 1. Транзакция при отсутствии буферизации.

close databases

open database d:\HomeLibrary\HomeLibrary.dbc

use Authors

select Authors

&&

begin transaction

         && Изменяем значения поля Author во всех записях таблицы

         replace all Author with Upper(Author)

end transaction

browse last

Пример 2. Транзакция при использовании буферизации.

close databases

open database d:\HomeLibrary\HomeLibrary.dbc

use Authors

select Authors

set multilocks on

&&

&& Активизируем буферизацию таблицы

CursorSetProp('Buffering', 5, 'Authors')

&&

&& Изменяем значения поля Author во всех записях таблицы

replace all Author with Proper(Author)

&&

begin transaction

         && Фиксируем изменения

         TableUpdate(1)

end transaction

browse last

Команда

ROLLBACK

отменяет изменения, выполненные в течение текущей транзакции.

Текущая транзакции после выполнения ROLLBACK завершается, поэтому употребление END TRANSACTION недопустимо.

Возникнет ошибка, если применить ROLLBACK вне транзакции, то есть перед вызовом ROLLBACK должна быть выполнена команда BEGIN TRANSACTION и не должна быть выполнена команда END TRANSACTION или ROLLBACK.

Если транзакция вложенная, то ROLLBACK отменяет изменения на текущем уровне транзакции.

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

Функция

TXNLEVEL( )

возвращает номер текущего уровня транзакции. Если транзакция не начата, то TXNLEVEL( ) вернет 0.

Функция

ISTRANSACTABLE([nWorkArea | cAlias])

возвращает .T., если свободная таблица или свободный курсор поддерживают транзакции, или .F. – в противном случае.

Функция

MAKETRANSACTABLE([nWorkArea | cAlias])

позволяет свободной таблице или свободному курсору поддерживать транзакции. Возвращает .T., если действие выполнено, или .F. – в противном случае.

Если функция выполнена успешно, то со свободной таблицей (курсором) можно употреблять управляющие транзакциями команды BEGIN TRANSACTION, END TRANSACTION и ROLLBACK.

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

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

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

Пример:

select test

if not Istransactable( ) then

Maketransactable( )

endif

if Istransactable( ) then

begin transaction

endif

&&

replace SomeField with 200

&&

if Istransactable( ) then

end transaction

endif