Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
PMO_PMS_shpory_final.docx
Скачиваний:
7
Добавлен:
17.09.2019
Размер:
457.71 Кб
Скачать

17. Транзакции в InterBase. Механизм транзакций. Параметры транзакций. Уровни изоляции и способы их задания в InterBase. Управление транзакциями. Примеры использования.

Где они живут

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

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

Словарик

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

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

уровень изолированности (или уровень изоляции) - как транзакция взаимодействует с другими, конкурирующими транзакциями.

commit, committed - завершение транзакции с применением изменений. Ничего лучше чем "подтверждение" или "подтвержденные" в качестве перевода этого термина я не нашел. В литературе также используется перевод "фиксация" и "зафиксированные".

rollback, rolled back - завершение транзакции с отменой всех изменений, которые были произведены в ее контексте. Русский перевод - отмена, отменены.

Существует 4 стандартных уровня (ANSI SQL-92) изолированности транзакций:

Dirty Read - "грязное" (или "незафиксирование") чтение. Транзакция может читать не подтверджденные изменения, сделанные в других транзакциях. В IB этот режим не поддерживается. Например, если транзакции A и B стартовали, и поменяли записи, то они обе видят изменения друг друга.

Read Committed - невоспроизводимое (или неповторяемое) чтение. Транзакция может читать только те изменения, которые были подтверждены другими транзакциями. Например, если транзакции A и B стартовали и поменяли записи, то они не видят изменения друг друга. Транзакция А увидит изменения транзакции B только тогда, когда транзакция B завершится по commit. Перечитывание данных в транзакции может выдавать разные результаты.

Repeatable Read - воспроизводимое (или повторяемое) чтение. Транзакция видит только те данные, которые существовали на момент ее старта.

Serialized - сериализуемость. Транзакция выполняются так, как будто никаких других транзакций в этот момент не существует. Или, транзакции выполняются так, как будто они выполняются последовательно. Не поддерживается явно в IB, но может быть сэмулировано.

транзакции - это пакет запросов, который последовательно производит изменения БД и либо принимается, если все изменения записи подтверждены, либо отвергается, если хоть один запрос завершился неуспешно. Запросы могут состоять из операторов SELECT / INSERT / UPDATE / DELETE, причем в контексте одной транзакции может быть как один такой запрос, так и множество запросов. Однако понятие " транзакция " гораздо глубже этого короткого определения.

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

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

Поясним эту суть на классическом примере перевода денег в банке с одного счета на другой.

Допустим, наша БД работает без транзакций, и нам нужно произвести упомянутый перевод. Тут мы можем поступить двумя разными способами:

Вначале снимаем деньги с одного счета, затем добавляем их к другому счету.

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

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

Определение параметров транзакции

Определение параметров транзакции выполняется оператором SET TRANSACTION, который имеет в стандарте SQL-92 следующее формальное описание:

TRANSACTION

{ ISOLATION LEVEL

{ READ UNCOMMITTED

| READ COMMITTED

| REPEATABLE READ

| SERIALIZABLE }

| { READ ONLY | READ WRITE }

| { DIAGNOSTICS SIZE count_message }

} , ... ;

Фраза ISOLATION LEVEL указывает устанавливаемый уровень изоляции.

Фраза READ ONLY устанавливает режим, при котором разрешается только чтение. Этот режим устанавливается по умолчанию, если уровень изоляции определен как READ UNCOMMITTED.

При режиме READ ONLY на данные не устанавливается никаких блокировок.

Фраза READ WRITE устанавливает режим, который разрешает как чтение, так и запись данных. При этом режиме уровень изоляции не может быть установлен как READ UNCOMMITTED.

Режим READ WRITE устанавливается по умолчанию для любого уровня, отличного от READ UNCOMMITTED.

Фраза DIAGNOSTICS SIZE определяет размер области, используемой для записи диагностических сообщений, доступ к которым осуществляется оператором GET DIAGNOSTICS.

Например, для определения транзакции, предотвращающей все описанные выше конфликтные ситуации, следует выполнить SQL-оператор

SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;

управление транзакциями

Необходимо помнить, что любое действие с базой данных происходит в рамках той или иной транзакции. Работа с InterBase основана на явном управлении транзакциями, а поскольку библиотека IBX - это "обертка" вокруг соответствующих функций InterBase API, то использование этих компонентов также предполагает, что программист явным образом будет управлять транзакциями из своего приложения. Для контроля транзакций в IBX существует специальный компонент TIBTransaction (рисунок 1):

Как видно из рисунка, компонент не слишком перегружен свойствами. Фактически основным является свойство Params, в котором можно указать уровень изоляции транзакции. Для этого необходимо знать соответствующие системные константы из InterBase API. Однако для большинства ситуаций хватит использования одного из четырех заранее заданных уровней изоляции. Для того чтобы выбрать один из них, можно вызвать редактор компонента (рисунок 2).

В появившемся диалоге можно указать нужный уровень изоляции, а и увидеть сразу, какими константами он задается (рисунок 3).

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

TIBTransaction ссылается на компонент базы данных при помощи свойства DetaultDatabase. Если также указать свойство DefaultTransaction у TIBDatabase, то в дальнейшем любые компоненты (TIBDataSet, TIBSQL и т.д.), которые ссылаются на TIBDatabase, будут автоматически "подхватывать" и указанную транзакцию.

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

SELECT *

FROM TABLE1

необходимо предварительно запустить транзакцию при помощи вызова IBTransaction.StartTransaction.

Такой "ручной" вызов не всегда удобен. Более того, каждый раз совершенно определенно известно: если хотим выполнить запрос, то должны запустить транзакцию. Чтобы избежать лишнего кода, связанного с запуском транзакций, можно установить значение свойства AllowAutoStart равным True. В этом случае если попробуем, например, открыть TIBDataSet, то он сам автоматически запустит соответствующую транзакцию.

Аналогичный смысл имеет свойство AutoStopAction. Когда закрываем все запросы, выполнявшиеся в контексте автоматически запущенной транзакции, то TIBTransaction выполняет действие, указанное в AutoStopAction. Например, автоматически подтверждает всю транзакцию при помощи метода Commit, если свойство AutoStopAction равно saCommit. Таким образом, разработчику предоставляется возможность указать, как компоненты должны автоматически взаимодействовать друг с другом.

Примеры использования

IBQuery->IBTransaction1->Commit();

IBQuery->IBTransaction1->Rallback();

начать и завершить транзакцию

Примерный набор параметров такой:

read

read_committed

rec_version

nowait

Параметры такой транзакции будут следующими:

write

concurrency

nowait

Для запросов, которые применяются для построения отчетов, однозначно нужно использовать транзакцию с режимом доступа "только для чтения" и с уровнем изоляции concurrency:

read

concurrency

nowait

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]