Всё в 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 COMMITTED делает стабильный снимок базы данных на время выполнения оператора. Каждый новый оператор верхнего уровня создаёт собственный моментальный снимок базы данных, чтобы видеть последние подтверждённые данные. Вложенные операторы (триггеры, вложенные хранимые процедуры и функции, динамические операторы и т. д.) используют тот же самый моментальный снимок базы данных, созданный оператором верхнего уровня. Таким образом обеспечивается согласованное чтение на момент начала выполнения оператора верхнего уровня. В Firebird 4.0 этот режим используется по умолчанию для транзакций с режимом изолированности READ COMMITTED.
В 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
|
Сами по себе блок |