Всё в Firebird выполняется в рамках транзакций.
Транзакция — логическая единица изолированной работы группы последовательных операций над базой данных.
Изменения над данными остаются обратимыми до тех пор, пока клиентское приложение не выдаст серверу инструкцию COMMIT
.
Firebird имеет небольшое количество SQL операторов, которые могут использоваться клиентскими приложениями для старта, управления, подтверждения или отмены транзакций, но достаточное для всех задач над базой данных:
- SET TRANSACTION
-
задание параметров транзакции и её старт;
- COMMIT
-
завершение транзакции и сохранение изменений;
- ROLLBACK
-
отмена изменений произошедший в рамках транзакции;
- SAVEPOINT
-
установка точки сохранения для частичного отката изменений, если это необходимо;
- RELEASE SAVEPOINT
-
удаление точки сохранения.
Задаёт параметры транзакции и стартует её.
DSQL, ESQL
SET TRANSACTION [NAME tr_name] [<tr_option> ...] <tr_option> ::= READ {ONLY | WRITE} | [NO] WAIT | [ISOLATION LEVEL] <isolation level> | NO AUTO UNDO | RESTART REQUESTS | IGNORE LIMBO | LOCK TIMEOUT seconds | AUTO COMMIT | RESERVING <tables> | USING <dbhandles> <isolation level> ::= SNAPSHOT [TABLE [STABILITY]] | SNAPSHOT AT NUMBER snapshot_number | READ COMMITTED [{[NO] RECORD_VERSION | READ CONSISTENCY}] <tables> ::= <table_spec> [, <table_spec> ...] <table_spec> ::= tablename [, tablename ...] [FOR [SHARED | PROTECTED] {READ | WRITE}] <dbhandles> ::= dbhandle [, dbhandle ...]
SET TRANSACTION
Параметр | Описание |
---|---|
tr_name |
Имя транзакции. Доступно только в ESQL. |
seconds |
Время ожидания оператора (statement) в секундах при возникновении конфликта. |
tables |
Список таблиц для резервирования. |
dbhandles |
Список баз данных, к которым база данных может получить доступ. Доступно только в ESQL. |
table_spec |
Спецификация резервирования таблицы. |
tablename |
Имя таблицы для резервирования. |
dbhandle |
Хендл базы данных, к которой транзакция может получить доступ. Доступно только в ESQL. |
snapshot number |
Номер снимка другой транзакци, данные снимка базы данных которой должны быть общими с новой транзакцией. |
Оператор SET TRANSACTION
задаёт параметры транзакции и стартует её.
Старт транзакции осуществляется только клиентскими приложениями, но не сервером (за исключением автономных транзакций и некоторых фоновых системных потоков/процессов, например, таких как sweep).
Каждое клиентское приложение может запускать произвольное количество одновременно выполняющихся транзакций. Фактически есть ограничение на общее количество выполняемых транзакций во всех клиентских приложениях, работающих с одной конкретной базой данных с момента последнего восстановления базы данных с резервной копии или с момента первоначального создания базы данных. Это количество равняется числу 248 -1 то есть ~ 2,8 x 1014 транзакций. В API и MON$ таблицах номер транзакции представляет собой 64 битное число.
Все предложения в операторе SET TRANSACTION
являются необязательными.
Если в операторе запуска транзакции на выполнение не задано никакого предложения, то предполагается старт транзакции со значениями всех характеристик по умолчанию (режим доступа, режим разрешения блокировок и уровень изолированности).
По умолчанию транзакция стартует со следующими характеристиками.
SET TRANSACTION
READ WRITE
WAIT ISOLATION LEVEL SNAPSHOT;
При старте со стороны клиента любой транзакции (заданной явно или по умолчанию) сервер передаёт клиенту дескриптор транзакции (целое число). На стороне сервера транзакциям последовательно присваиваются номера.
Этот номер средствами SQL можно получить, используя контекстную переменную CURRENT_TRANSACTION
.
Основными характеристиками транзакции являются:
-
режим доступа к данным (
READ WRITE
,READ ONLY
); -
режим разрешения блокировок (
WAIT
,NO WAIT
) с возможным дополнительным уточнениемLOCK TIMEOUT
; -
уровень изоляции (
READ COMMITTED
,SNAPSHOT
,SNAPSHOT TABLE STABILITY
); -
средства резервирования или освобождения таблиц (предложение
RESERVING
).
Необязательное предложение NAME
задаёт имя транзакции.
Предложение NAME
доступно только в Embedded SQL.
Если предложение NAME не указано, то оператор SET TRANSACTION
применяется к транзакции по умолчанию.
За счёт именованных транзакций позволяется одновременный запуск нескольких активных транзакций в одном приложении.
При этом должна быть объявлена и инициализирована одноименная переменная базового языка.
В DSQL, это ограничение предотвращает динамическую спецификацию имён транзакций.
Для транзакций существует два режима доступа к данным базы данных: READ WRITE
и READ ONLY
.
-
При режиме доступа
READ WRITE
операции в контексте данной транзакции могут быть как операциями чтения, так и операциями изменения данных. Это режим по умолчанию. -
В режиме
READ ONLY
в контексте данной транзакции могут выполняться только операции выборки данныхSELECT
. Любая попытка изменения данных в контексте такой транзакции приведёт к исключениям базы данных. Однако это не относиться к глобальным временным таблицам (GTT), которые разрешено модифицировать вREAD ONLY
транзакциях.
В Firebird API для режимов доступа предусмотрены следующие константы: isc_tpb_write
соответствует режиму READ WRITE
, isc_tpb_read
— READ ONLY
.
При работе с одной и той же базой данных нескольких клиентских приложений могут возникать блокировки. Блокировки могут возникать, когда одна транзакция вносит неподтверждённые изменения в строку таблицы или удаляет строку, а другая транзакция пытается изменять или удалять эту же строку. Такие блокировки называются конфликтом обновления.
Блокировки также могут возникнуть и в других ситуациях при использовании некоторых уровней изоляции транзакций.
Существуют два режима разрешения блокировок: WAIT
и NO WAIT
.
В режиме WAIT
(режим по умолчанию) при появлении конфликта с параллельными транзакциями, выполняющими конкурирующие обновления данных в той же базе данных, такая транзакция будет ожидать завершения конкурирующей транзакции путём её подтверждения (COMMIT
) или отката (ROLLBACK
). Иными словами, клиентское приложение будет переведено в режим ожидания до момента разрешения конфликта.
Если для режима WAIT
задать предложение LOCK TIMEOUT
, то ожидание будет продолжаться только указанное в этом предложении количество секунд.
По истечении этого срока будет выдано сообщение об ошибке: “Lock time-out on wait transaction” (Истечение времени ожидания блокировки для транзакции WAIT
).
Этот режим даёт несколько отличные формы поведения в зависимости от уровня изоляции транзакций.
В Firebird API режиму WAIT
соответствует константа isc_tpb_wait
.
Если установлен режим разрешения блокировок NO WAIT
, то при появлении конфликта блокировки данная транзакция немедленно вызовет исключение базы данных.
В Firebird API режиму NO WAIT
соответствует константа isc_tpb_nowait
.
Note
|
|
Уровень изолированности транзакций — значение, определяющее уровень, при котором в транзакции допускаются несогласованные данные, то есть степень изолированности одной транзакции от другой. Изменения, внесённые некоторым оператором, будут видны всем последующим операторам, запущенным в рамках этой же транзакции, независимо от её уровня изолированности. Изменения произведённые в рамках другой транзакции остаются невидимыми для текущей транзакции до тех пор, пока они не подтверждены. Уровень изолированности, а иногда, другие атрибуты, определяет, как транзакции будут взаимодействовать с другой транзакцией, которая хочет подтвердить изменения.
Необязательное предложение ISOLATION LEVEL
задаёт уровень изолированности запускаемой транзакции.
Это самая важная характеристика транзакции, которая определяет её поведение по отношению к другим одновременно выполняющимся транзакциям.
Существует три уровня изолированности транзакции:
-
SNAPSHOT
-
SNAPSHOT TABLE STABILITY
-
READ COMMITTED
с уточнениями (NO RECORD_VERSION
илиRECORD_VERSION
илиREAD CONSISTENCY
)
Уровень изолированности SNAPSHOT
(уровень изолированности по умолчанию) означает, что этой транзакции видны лишь те изменения, фиксация которых произошла не позднее момента старта этой транзакции.
Любые подтверждённые изменения, сделанные другими конкурирующими транзакциями, не будут видны в такой транзакции в процессе ее активности без её перезапуска.
Чтобы увидеть эти изменения, нужно завершить транзакцию (подтвердить её или выполнить полный откат, но не откат на точку сохранения) и запустить транзакцию заново.
Note
|
Изменения, вносимые автономными транзакциями, также не будут видны в контексте той (“внешней”) транзакции, которая запустила эти автономные транзакции, если она работает в режиме |
В Firebird API режиму изолированности SNAPSHOT
соответствует константа isc_tpb_concurrency
.
Транзакцию с уровнем изолированности SNAPSHOT
можно запустить на основе другой транзакции, если известен номер её снимка.
В этом случае эта новая транзакция может видеть те же самые данные, что и транзакция на основе которой она запущена.
Эта функциональность позволяет создать параллельные процессы (в разных подключениях), считывающие согласованные данные из базы данных. Например, процесс резервного копирования может создавать несколько потоков, параллельно считывающих данные из базы данных. Или веб-служба работать с распредёленными вспомогательными службами, выполняя некоторую обработку.
Это достигается созданием транзакции с использованием синтаксиса
SET TRANSACTION SNAPSHOT AT NUMBER snapshot_number
или через API с использованием константы isc_tpb_at_snapshot_number
.
Значение snapshot_number из первой транзакции можно получить используя следующий запрос
RDB$GET_CONTEXT('SYSTEM', 'SNAPSHOT_NUMBER')
или через API информации о транзакции с константой fb_info_tra_snapshot_number
.
Note
|
Обратите внимание, snapshot_number должен быть номером снимка активной транзакции. |
Уровень изоляции транзакции SNAPSHOT TABLE STABILITY
позволяет, как и в случае SNAPSHOT
, также видеть только те изменения, фиксация которых произошла не позднее момента старта этой транзакции.
При этом после старта такой транзакции в других клиентских транзакциях невозможно выполнение изменений ни в каких таблицах этой базы данных, уже каким-либо образом измененных первой транзакцией.
Все такие попытки в параллельных транзакциях приведут к исключениям базы данных.
Просматривать любые данные другие транзакции могут совершенно свободно.
При помощи предложения резервирования RESERVING
можно разрешить другим транзакциям изменять данные в некоторых таблицах.
Если на момент старта клиентом транзакции с уровнем изоляции SNAPSHOT TABLE STABILITY
какая-нибудь другая транзакция выполнила неподтверждённое изменение данных любой таблицы базы данных, то запуск транзакции с таким уровнем изоляции приведёт к ошибке базы данных.
В Firebird API режиму изолированности SNAPSHOT TABLE STABILITY
соответствует константа isc_tpb_consistency
.
Уровень изолированности READ COMMITTED
позволяет в транзакции без её перезапуска видеть все подтверждённые изменения данных базы данных, выполненные в других параллельных транзакциях.
Неподтверждённые изменения не видны в транзакциях этого уровня изолированности.
Для получения обновлённого списка строк интересующей таблицы необходимо лишь повторное выполнение оператора SELECT
в рамках активной транзакции READ COMMITTED
без её перезапуска.
В Firebird API режиму изолированности READ COMMITTED
соответствует константа isc_tpb_read_committed
.
Для этого уровня изолированности можно указать один из двух значений дополнительной характеристики в зависимости от желаемого способа разрешения конфликтов: RECORD_VERSION
и NO RECORD_VERSION
.
Как видно из их имён они являются взаимоисключающими.
-
NO RECORD_VERSION
является в некотором роде механизмом двухфазной блокировки. В этом случае транзакция не может прочитать любую запись, которая была изменена параллельной активной (неподтвержденной) транзакцией.-
Если указана стратегия разрешения блокировок
NO WAIT
, то будет немедленно выдано соответствующее исключение. -
Если указана стратегия разрешения блокировок
WAIT
, то это приведёт к ожиданию завершения или откату конкурирующей транзакции. Если конкурирующая транзакция откатывается, или, если она завершается и её идентификатор старее (меньше), чем идентификатор текущей транзакции, то изменения в текущей транзакции допускаются. Если конкурирующая транзакция завершается и её идентификатор новее (больше), чем идентификатор текущей транзакции, то будет выдана ошибка конфликта блокировок.
-
-
При задании
RECORD_VERSION
транзакция всегда читает последнюю подтверждённую версию записей таблиц, независимо от того, существуют ли изменённые и ещё не подтверждённые версии этих записей. В этом случае режим разрешения блокировок (WAIT
илиNO WAIT
) никак не влияет на поведение транзакции при её старте.
В Firebird API для способа разрешения конфликтов NO RECORD_VERSION
соответствует константа isc_tpb_no_rec_version
,
а RECORD_VERSION
— isc_tpb_rec_version
.
Warning
|
Начиная с Firebird 4.0 эти опции являются устаревшими.
По умолчанию они игнорируются и запускается транзакция |
Если указана эта опция, то транзакция с режимом изолированности READ COMMITED
делает стабильный снимок базы данных на время выполнения оператора.
Каждый новый оператор верхнего уровня создает собственный моментальный снимок базы данных, чтобы видеть последние потверждённые данные.
Вложенные операторы (триггеры, вложенные хранимые процедуры и функции, динамические операторы и т.
д.) используют тот же самый моментальный снимок базы данных, созданный оператором верхнего уровня.
Таким образом обеспечивается согласованное чтение на момент начала выполнения оператора верхнего уровня.
В Firebird 4.0 этот режим используется по умолчанию для транзакций с режимом изолированности READ COMMITED
.
В Firebird API для стабильного снимка на уровне SQL оператора READ CONSISTENCY
соответствует константа isc_tpb_read_consistency
.
Когда оператор выполняется в транзакции с режимом изолированности READ COMMITTED READ CONSISTENCY
вид базы данных неизменен (подобно транзакции SNAPSHOT
). Поэтому бесполезно ждать фиксации параллельной транзакции в надежде перечитать новую версию зафиксированной записи.
При чтении поведение похоже на транзакцию READ COMMITTED RECORD_VERSION
— оператор не ждёт завершения активной транзакции и обходит цепочку бекверсий, в которой ищет версию записи видимую для текущего моментального снимка.
Для режима изолированности READ COMMITTED READ CONSISTENCY
обработка конфликтов обновлений Firebird значительно изменяется.
При обнаружении конфликта обновления выполняется следующее:
-
режим изолированности транзакции временно переключается в режим
READ COMMITTED NO RECORD VERSION
; -
Firebird устанавливает блокировку записи на конфликтную запись;
-
Firebird продолжает оценивать оставшиеся записи для удаления/обновления в курсоре, а также продолжает ставить на них блокировки;
-
когда больше нет записей для извлечения, запускается механизм для отмены всех выполненных действий, выполненных оператором верхнего уровня, и сохраняются все установленные блокировки для каждой обновлённой/удалённой/заблокированной записи, все вставленные записи удаляются;
-
затем Firebird восстанавливает режим изолированности транзакции как
READ COMMITTED READ CONSISTENCY
, создает новый снимок уровня оператора и перезапускает выполнение оператора верхнего уровня.
Такой алгоритм позволяет гарантировать, что после перезапуска уже обновленные записи останутся заблокированными, они будут видны новому снимку и могут быть обновлены снова без дальнейших конфликтов. Кроме того, из-за режима согласованности чтения набор измененных записей остается согласованным.
Note
|
Замечания
|
При использовании опции NO AUTO UNDO
оператор ROLLBACK
только помечает транзакцию как отменённую без удаления созданных в этой транзакции версий, которые будут удалены позднее в соответствии с выбранной политикой сборки мусора (см. параметр GCPolicy
в firebird.conf).
Эта опция может быть полезна при выполнении транзакции, в рамках которой производится много отдельных операторов, изменяющих данные, и при этом есть уверенность, что эта транзакция будет чаще всего завершаться успешно, а не откатываться.
Для транзакций, в рамках которых не выполняется никаких изменений, опция NO AUTO UNDO
игнорируется.
При указании опции IGNORE LIMBO
игнорируются записи, создаваемые “потерянными” (т.е.
не завершёнными) транзакциями (limbo transaction). Транзакции считается “потерянной”, если не завершён второй этап двухфазного подтверждения (two-phase commit).
При указании опции AUTO COMMIT
транзакция автоматически подтверждается после успешного выполнения любого оператора.
Если в процессе выполнения оператора произойдёт ошибка, то транзакция будет откачена.
После подтверждения или отката транзакция продолжает оставаться активной, сохраняя свой идентификатор.
Important
|
Опция |
Предложение RESERVING
в операторе SET TRANSACTION
резервирует указанные в списке таблицы.
Резервирование запрещает другим транзакциям вносить в эти таблицы изменения или (при определённых установках характеристик предложения резервирования) даже читать данные из этих таблиц, в то время как выполняется данная транзакция.
Либо, наоборот, в этом предложении можно указать список таблиц, в которые параллельные транзакции могут вносить изменения, даже если запускается транзакция с уровнем изоляции SNAPSHOT TABLE STABILITY
.
В одном предложении резервирования можно указать произвольное количество резервируемых таблиц используемой базы данных.
Если опущено одно из ключевых слов SHARED
или PROTECTED
, то предполагается SHARED
.
Если опущено все предложение FOR
, то предполагается FOR SHARED READ
.
Варианты осуществления резервирования таблиц по их названиям не являются очевидными.
|
SHARED READ |
SHARED WRITE |
PROTECTED READ |
PROTECTED WRITE |
SHARED READ |
да |
да |
да |
да |
SHARED WRITE |
да |
да |
нет |
нет |
PROTECTED READ |
да |
нет |
да |
нет |
PROTECTED WRITE |
да |
нет |
нет |
нет |
Для транзакции запущенной в режиме изолированности SNAPSHOT
для таблиц, указанных в предложении RESERVING
, в параллельных транзакциях в зависимости от их уровня изоляции допустимы при различных способах их резервирования следующие варианты поведения:
-
SHARED READ
— не оказывает никакого влияния на выполнение параллельных транзакций; -
SHARED WRITE
— на поведение параллельных транзакций с уровнями изолированностиSNAPSHOT
иREAD COMMITTED
не оказывает никакого влияния, для транзакций с уровнем изолированностиSNAPSHOT TABLE STABILITY
запрещает не только запись, но также и чтение данных из указанных таблиц; -
PROTECTED READ
— допускает только чтение данных из резервируемых таблиц для параллельных транзакций с любым уровнем изолированности, попытка внесения изменений приводит к исключению базы данных; -
PROTECTED WRITE
— для параллельных транзакций с уровнями изолированностиSNAPSHOT
иREAD COMMITTED
запрещает запись в указанные таблицы, для транзакций с уровнем изолированностиSNAPSHOT TABLE STABILITY
запрещает также и чтение данных из резервируемых таблиц.
Для транзакции запущенной в режиме изолированности SNAPSHOT TABLE STABILITY
для таблиц, указанных в предложении RESERVING
, в параллельных транзакциях в зависимости от их уровня изолированности допустимы при различных способах их резервирования следующие варианты поведения:
-
SHARED READ
— позволяет всем параллельным транзакциям независимо от их уровня изолированности не только читать, но и выполнять любые изменения в резервируемых таблицах (если параллельная транзакция имеет режим доступаREAD WRITE
); -
SHARED WRITE
— для всех параллельных транзакций с уровнем доступаREAD WRITE
и с уровнями изолированностиSNAPSHOT
иREAD COMMITTED
позволяет читать данные из таблиц и писать данные в указанные таблицы, для транзакций с уровнем изолированностиSNAPSHOT TABLE STABILITY
запрещает не только запись, но также и чтение данных из указанных таблиц; -
PROTECTED READ
— допускает только лишь чтение данных из резервируемых таблиц для параллельных транзакций с любым уровнем изолированности; -
PROTECTED WRITE
— для параллельных транзакций с уровнями изолированностиSNAPSHOT
иREAD COMMITTED
запрещает запись в указанные таблицы, для транзакций с уровнем изолированностиSNAPSHOT TABLE STABILITY
запрещает также и чтение данных из резервируемых таблиц.
Для транзакции запущенной в режиме изолированности READ COMMITTED
для таблиц, указанных в предложении RESERVING
, в параллельных транзакциях в зависимости от их уровня изоляции допустимы при различных способах их резервирования следующие варианты поведения:
-
SHARED READ
— позволяет всем параллельным транзакциям независимо от их уровня изолированности не только читать, но и выполнять любые изменения в резервируемых таблицах (при уровне доступаREAD WRITE
); -
SHARED WRITE
— для всех транзакций с уровнем доступаREAD WRITE
и с уровнями изолированностиSNAPSHOT
иREAD COMMITTED
позволяет читать и писать данные в указанные таблицы, для транзакций с уровнем изолированностиSNAPSHOT TABLE STABILITY
запрещает не только запись, но также и чтение данных из указанных таблиц; -
PROTECTED READ
— допускает только чтение данных из резервируемых таблиц для параллельных транзакций с любым уровнем изолированности; -
PROTECTED WRITE
— для параллельных транзакций с уровнями изолированностиSNAPSHOT
иREAD COMMITTED
разрешает только чтение данных и запрещает запись в указанные в данном списке таблицы, для транзакций с уровнем изолированностиSNAPSHOT TABLE STABILITY
запрещает не только изменение данных, но и чтение данных из резервируемых таблиц.
Tip
|
Предложение |
Подтверждение транзакции.
DSQL, ESQL
COMMIT [WORK] [TRANSACTION tr_name] [RELEASE] [RETAIN [SNAPSHOT]];
COMMIT
Параметр | Описание |
---|---|
tr_name |
Имя транзакции. Доступно только в ESQL. |
Оператор COMMIT
подтверждает все изменения в данных, выполненные в контексте данной транзакции (добавления, изменения, удаления). Новые версии записей становятся доступными для других транзакций, и если предложение RETAIN
не используется, то освобождаются все ресурсы сервера, связанные с выполнением данной транзакции.
Если в процессе подтверждения транзакции возникли ошибки в базе данных, то транзакция не подтверждается. Пользовательская программа должна обработать ошибочную ситуацию и заново подтвердить транзакцию или выполнить ее откат.
Необязательное предложение TRANSACTION
задаёт имя транзакции.
Предложение TRANSACTION
доступно только в Embedded SQL.
Если предложение TRANSACTION
не указано, то оператор COMMIT
применяется к транзакции по умолчанию.
Note
|
За счёт именованных транзакций позволяется одновременный запуск нескольких активных транзакций в одном приложении. При этом должна быть объявлена и инициализирована одноименная переменная базового языка. В DSQL, это ограничение предотвращает динамическую спецификацию имён транзакций. |
Необязательное ключевое слово WORK
может быть использовано лишь для совместимости с другими системами управления реляционными базами данных.
Ключевое слово RELEASE
доступно только в Embedded SQL.
Оно позволяет отключиться ото всех баз данных после завершения текущей транзакции. RELEASE
поддерживается только для обратной совместимости со старыми версиями Interbase.
В настоящее время вместо него используется оператор ESQL DISCONNECT
.
Если используется предложение RETAIN [SNAPSHOT]
, то выполняется так называемое мягкое (soft) подтверждение.
Выполненные действия в контексте данной транзакции фиксируются в базе данных, а сама транзакция продолжает оставаться активной, сохраняя свой идентификатор, а также состояние курсоров, которое было до мягкой фиксации транзакции.
В этом случае нет необходимости опять стартовать транзакцию и заново выполнять оператор SELECT
для получения данных.
Если уровень изоляции такой транзакции SNAPSHOT
или SNAPSHOT TABLE STABILITY
, то после мягкого подтверждения транзакция продолжает видеть состояние базы данных, которое было при первоначальном запуске транзакции, то есть клиентская программа не видит новых подтверждённых результатов изменения данных других транзакций.
Кроме того, мягкое подтверждение не освобождает ресурсов сервера (открытые курсоры не закрываются).
Tip
|
Для транзакций, которые выполняют только чтение данных из базы данных, рекомендуется также использовать оператор |
Откат транзакции.
DSQL, ESQL
ROLLBACK [WORK] [TRANSACTION tr_name] [RETAIN [SNAPSHOT] | TO SAVEPOINT sp_name] [RELEASE];
ROLLBACK
Параметр | Описание |
---|---|
tr_name |
Имя транзакции. Доступно только в ESQL. |
sp_name |
Имя точки сохранения. Доступно только в DSQL. |
Оператор ROLLBACK
отменяет все изменения данных базы данных (добавление, изменение, удаление), выполненные в контексте этой транзакции.
Оператор ROLLBACK
никогда не вызывает ошибок.
Если не указано предложение RETAIN
, то при его выполнении освобождаются все ресурсы сервера, связанные с выполнением данной транзакции.
Необязательное предложение TRANSACTION
задаёт имя транзакции.
Предложение TRANSACTION
доступно только в Embedded SQL.
Если предложение TRANSACTION
не указано, то оператор ROLLBACK
применяется к транзакции по умолчанию.
Note
|
За счёт именованных транзакций позволяется одновременный запуск нескольких активных транзакций в одном приложении. При этом должна быть объявлена и инициализирована одноименная переменная базового языка. В DSQL, это ограничение предотвращает динамическую спецификацию имён транзакций. |
Необязательное ключевое слово WORK
может быть использовано лишь для совместимости с другими системами управления реляционными базами данных.
Ключевое слово RETAIN
указывает, что все действия по изменению данных в контексте этой транзакции, отменяются, а сама транзакция продолжает оставаться активной, сохраняя свой идентификатор, а также состояние курсоров, которое было до мягкой фиксации транзакции.
Таким образом, выделенные ресурсы для транзакции не освобождаются.
Для уровней изоляции SNAPSHOT
и SNAPSHOT TABLE STABILITY
состояние базы данных остаётся в том виде, которое база данных имела при первоначальном старте такой транзакции, однако в случае уровня изоляции READ COMMITTED
база данных будет иметь вид, соответствующий новому
состоянию на момент выполнения оператора ROLLBACK RETAIN
.
В случае отмены транзакции с сохранением её контекста нет необходимости заново выполнять оператор SELECT
для получения данных из таблицы.
Необязательное предложение TO SAVEPOINT
в операторе ROLLBACK
задаёт имя точки сохранения, на которую происходит откат.
В этом случае отменяются все изменения, произошедшие в рамках транзакции, начиная с созданной точки сохранения (SAVEPOINT
).
Оператор ROLLBACK TO SAVEPOINT
выполняет следующие операции:
-
Все изменения в базе данных, выполненные в рамках транзакции начиная с созданной точки сохранения, отменяются. Пользовательские переменные, заданные с помощью функции
RDB$SET_CONTEXT()
остаются неизменными; -
Все точки сохранения, создаваемые после названной, уничтожаются. Все более ранние точки сохранения, как сама точка сохранения, остаются. Это означает, что можно откатываться к той же точке сохранения несколько раз;
-
Все явные и неявные блокированные записи, начиная с точки сохранения, освобождаются. Другие транзакции, запросившие ранее доступ к строкам, заблокированным после точки сохранения, должны продолжать ожидать, пока транзакция не фиксируется или откатывается. Другие транзакции, которые ещё не запрашивали доступ к этим строкам, могут запросить и сразу же получить доступ к разблокированным строкам.
Создание точки сохранения.
DSQL
SAVEPOINT sp_name
SAVEPOINT
Параметр | Описание |
---|---|
sp_name |
Имя точки сохранения. Должно быть уникальным в рамках транзакции. |
Оператор SAVEPOINT
создаёт SQL:99 совместимую точку сохранения, к которой можно позже откатывать работу с базой данных, не отменяя все действия, выполненные с момента старта транзакции.
Механизмы точки сохранения также известны под термином “вложенные транзакции” (“nested transactions”).
Если имя точки сохранения уже существует в рамках транзакции, то существующая точка сохранения будет удалена, и создаётся новая с тем же именем.
Для отката изменений к точке сохранения используется оператор ROLLBACK TO SAVEPOINT.
Note
|
Внутренний механизм точек сохранения может использовать большие объёмы памяти, особенно если вы обновляете одни и те же записи многократно в одной транзакции. Если точка сохранения уже не нужна, но вы ещё не готовы закончить транзакцию, то можно ее удалить оператором RELEASE SAVEPOINT, тем самым освобождая ресурсы. |
CREATE TABLE TEST (ID INTEGER);
COMMIT;
INSERT INTO TEST VALUES (1);
COMMIT;
INSERT INTO TEST VALUES (2);
SAVEPOINT Y;
DELETE FROM TEST;
SELECT * FROM TEST; -- возвращает пустую строку
ROLLBACK TO Y;
SELECT * FROM TEST; -- возвращает две строки
ROLLBACK;
SELECT * FROM TEST; -- возвращает одну строку
Удаление точки сохранения.
DSQL
RELEASE SAVEPOINT sp_name [ONLY]
RELEASE SAVEPOINT
Параметр | Описание |
---|---|
sp_name |
Имя точки сохранения. |
Оператор RELEASE SAVEPOINT
удаляет именованную точку сохранения, освобождая все связанные с ней ресурсы.
По умолчанию удаляются также все точки сохранения, создаваемые после указанной.
Если указано предложение ONLY
, то удаляется только точка сохранения с заданным именем.
По умолчанию сервер использует автоматическую системную точку сохранения уровня транзакции для выполнения её отката.
При выполнении оператора ROLLBACK
, все изменения, выполненные в транзакции, откатываются до системной точки сохранения и после этого транзакция подтверждается.
Когда объем изменений, выполняемых под системной точкой сохранения уровня транзакции, становиться большим (затрагивается порядка 50000 записей), сервер освобождает системную точку сохранения и, при необходимости отката транзакции, использует механизм TIP.
Tip
|
Если вы ожидаете, что объем изменений в транзакции будет большим, то можно задать опцию |
Использование операторов управления транзакциями в PSQL не разрешается, так как это нарушит атомарность оператора, вызывающего процедуру. Но Firebird поддерживает вызов и обработку исключений в PSQL, так, чтобы действия, выполняемые в хранимых процедурах и триггерах, могли быть выборочно отменены без полного отката всех действий в них. Внутренне автоматические точки сохранения используется для:
-
отмены всех действий внутри блока
BEGIN … END
, где происходит исключение; -
отмены всех действий, выполняемых в хранимой процедуре/триггере (или, в случае селективной хранимой процедуры, всех действий, выполненных с момента последнего оператора
SUSPEND
), если они завершаются преждевременно из-за непредусмотренной ошибки или исключения.
Каждый блок обработки исключений PSQL также ограничен автоматическими точками сохранения сервера.
Note
|
Сами по себе блок |