FirebirdSQL logo
RECORD_VERSION

Для этого уровня изолированности можно указать один из двух значений дополнительной характеристики в зависимости от желаемого способа разрешения конфликтов: 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_versionRECORD_VERSION — isc_tpb_rec_version.

Warning

Начиная с Firebird 4.0 эти опции являются устаревшими.По умолчанию они игнорируются и запускается транзакция READ COMMITTED READ CONSISTENCY.Это можно изменить установив параметр ReadConsistency (см. firebird.conf) в 0.В этом случае опции не игнорируются и работают точно так же как в предыдущих версиях.В будущих версиях этот параметр в firebird.conf может быть удалён.

READ CONSISTENCY

Если указана эта опция, то транзакция с режимом изолированности 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 значительно изменяется.При обнаружении конфликта обновления выполняется следующее:

  1. режим изолированности транзакции временно переключается в режим READ COMMITTED NO RECORD VERSION;

  2. Firebird устанавливает блокировку записи на конфликтную запись;

  3. Firebird продолжает оценивать оставшиеся записи для удаления/обновления в курсоре, а также продолжает ставить на них блокировки;

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

  5. затем Firebird восстанавливает режим изолированности транзакции как READ COMMITTED READ CONSISTENCY, создаёт новый снимок уровня оператора и перезапускает выполнение оператора верхнего уровня.

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

Note
Замечания
  • Приведённый выше алгоритм перезапуска применяется к операторам UPDATE, DELETE, SELECT WITH LOCK и MERGE, с предложением RETURNING и без него, выполняемым непосредственно из пользовательского приложения или в составе некоторого объекта PSQL (хранимая процедура, функция, триггер, EXECUTE BLOCK и т. д.);

  • если оператор UPDATE/DELETE расположена на каком-то явном курсоре (WHERE CURRENT OF), то Firebird пропускает шаг (c) выше, то есть не извлекает и не устанавливает блокировки записи для оставшихся записей курсора;

  • если оператор верхнего уровня SELECT (или EXECUTE BLOCK возвращающий набор данных) и конфликт обновления происходит после того, как одна или несколько записей были возвращены приложению, то ошибка конфликта обновления сообщается как обычно и перезапуск не инициируется;

  • рестарт не инициируется для операторов в автономных блоках (IN AUTONOMOUS TRANSACTION DO …​);

  • после 10 попыток Firebird прерывает алгоритм перезапуска, снимает все блокировки записи, восстанавливает режим изоляции транзакции как READ COMMITTED READ CONSISTENCY и сообщает о конфликте обновления;

  • любая не обработанная ошибка на шаге (c) выше останавливает алгоритм перезапуска, и Firebird продолжает обработку обычным способом, например, ошибка может быть перехвачена и обработана блоком PSQL WHEN или сообщена приложению, если она не обработана;

  • триггеры UPDATE/DELETE сработают многократно для одной и той же записи, если выполнение оператора было перезапущено и запись обновлена/удалена снова;

  • по историческим причинам isc_update_conflict сообщается как вторичный код ошибки с первичным кодом ошибки isc_deadlock.

NO AUTO UNDO

При использовании опции NO AUTO UNDO оператор ROLLBACK только помечает транзакцию как отменённую без удаления созданных в этой транзакции версий, которые будут удалены позднее в соответствии с выбранной политикой сборки мусора (см. параметр GCPolicy в firebird.conf).

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

Для транзакций, в рамках которых не выполняется никаких изменений, опция NO AUTO UNDO игнорируется.

IGNORE LIMBO

При указании опции IGNORE LIMBO игнорируются записи, создаваемые “потерянными” (т.е.не завершёнными) транзакциями (limbo transaction). Транзакции считается “потерянной”, если не завершён второй этап двухфазного подтверждения (two-phase commit).