Spec-Zone.ru › SQLite

Транзакция

1. Синтаксис управления транзакциями

begin-stmt:

НАЧАТЬ ЭКСКЛЮЗИВНО ТРАНЗАКЦИЯ ОТЛОЖЕННАЯ НЕМЕДЛЕННАЯ

commit-stmt:

ФИКСИРОВАТЬ ТРАНЗАКЦИЯ КОНЕЦ

rollback-stmt:

ОТКАТ ТРАНЗАКЦИИ ДО ТОЧКИ_СОХРАНЕНИЯ имя_точки_сохранения

2. Транзакции

Чтение или запись данных происходят только в рамках транзакции. Любая команда, которая обращается к базе данных (по существу, любая команда SQL, за исключением некоторых команд PRAGMA), автоматически начнет транзакцию, если она еще не запущена. Автоматически запущенные транзакции завершаются подтверждением, когда завершается последняя команда SQL.

Транзакции могут быть начаты вручную с помощью команды BEGIN. Такие транзакции обычно сохраняются до следующей команды COMMIT или ROLLBACK. Но транзакция также будет откачена, если база данных будет закрыта или произойдет ошибка, и алгоритм разрешения конфликтов ROLLBACK будет указан. Дополнительную информацию об алгоритме разрешения конфликтов ROLLBACK см. в документации по предложению ON CONFLICT.

END TRANSACTION является псевдонимом для COMMIT.

Транзакции, созданные с помощью BEGIN...COMMIT, не вложены. Для вложенных транзакций используйте команды SAVEPOINT и RELEASE. Оператор ROLLBACK с фрагментом "TO SAVEPOINT имя" на диаграмме синтаксиса применим только к транзакциям SAVEPOINT. Попытка вызвать команду BEGIN в рамках транзакции завершится ошибкой, независимо от того, была ли транзакция запущена с помощью SAVEPOINT или предыдущей командой BEGIN. Команда COMMIT и команда ROLLBACK без фрагмента TO работают одинаково в транзакциях SAVEPOINT так же, как и в транзакциях, начатых с BEGIN.

2.1. Чтение транзакций против записи транзакций

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

Чтение транзакции используется только для чтения. Запись транзакции позволяет как читать, так и записывать. Чтение транзакции запускается оператором SELECT, а запись транзакции запускается операторами, такими как CREATE, DELETE, DROP, INSERT или UPDATE (в совокупности "операторы записи"). Если оператор записи выполняется при активной транзакции чтения, то транзакция чтения может быть преобразована в запись, если это возможно. Если какое-либо другое подключение к базе данных уже изменило базу данных или находится в процессе изменения базы данных, то преобразование в запись невозможно, и оператор записи завершится ошибкой SQLITE_BUSY.

В то время как активна операция чтения, любые изменения в базе данных, внесенные отдельными подключениями к базе данных, не будут видны подключению к базе данных, которое инициировало операцию чтения. Если подключение к базе данных X выполняет операцию чтения, возможно, что какое-то другое подключение к базе данных Y может изменить содержимое базы данных, пока транзакция X все еще открыта, однако X не сможет увидеть эти изменения до завершения транзакции. Пока активна операция чтения, X будет продолжать видеть историческую «мгновенную фотографию» базы данных до внесения изменений, произведенных Y.

2.2. Транзакции DEFERRED, IMMEDIATE и EXCLUSIVE

Транзакции могут быть DEFERRED, IMMEDIATE или EXCLUSIVE. По умолчанию используется поведение DEFERRED.

DEFERRED означает, что транзакция фактически не начинается до первого доступа к базе данных. Внутренне оператор BEGIN DEFERRED просто устанавливает флаг в подключении к базе данных, отключающий автоматическое подтверждение, которое обычно происходит по завершении последней команды. Это заставляет транзакцию, которая автоматически запускается, сохраняться до явного COMMIT или ROLLBACK или до отката, вызванного ошибкой или предложением ON CONFLICT ROLLBACK. Если первой командой после BEGIN DEFERRED является SELECT, то запускается транзакция чтения. Последующие команды записи будут обновлять транзакцию до транзакции записи, если это возможно, или возвращать SQLITE_BUSY. Если первой командой после BEGIN DEFERRED является команда записи, то запускается транзакция записи.

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

EXCLUSIVE аналогично IMMEDIATE в том, что транзакция записи запускается немедленно. EXCLUSIVE и IMMEDIATE совпадают в режиме WAL, но в других режимах ведения журнала EXCLUSIVE предотвращает чтение базы данных другими подключениями во время выполнения транзакции.

2.3. Неявные и явные транзакции

Неявная транзакция (транзакция, которая запускается автоматически, а не транзакция, запускаемая с помощью BEGIN) автоматически подтверждается при завершении последней активной команды. Команда завершается, когда закрывается последний указатель курсора, что гарантируется при сбросе подготовленной команды reset или finalized. Некоторые команды могут «завершиться» в целях управления транзакциями до сброса или завершения, но в этом нет гарантии. Единственный способ гарантировать, что команда «завершилась», — вызвать sqlite3_reset() или sqlite3_finalize() для этой команды. Открытый sqlite3_blob, используемый для инкрементного ввода-вывода BLOB, также считается незавершенной командой. sqlite3_blob завершается при его закрытии close.

Явная команда COMMIT выполняется немедленно, даже если существуют ожидающие команды SELECT. Однако, если есть ожидающие операции записи, команда COMMIT завершится ошибкой с кодом SQLITE_BUSY.

Попытка выполнить COMMIT также может привести к возврату SQLITE_BUSY, если другой поток или процесс имеет открытое подключение для чтения. Когда COMMIT завершается таким образом, транзакция остается активной, и COMMIT можно повторить позже, после того как читатель сможет очистить.

В очень старых версиях SQLite (до версии 3.7.11 — 2012-03-20) ROLLBACK завершится ошибкой SQLITE_BUSY, если есть какие-либо ожидающие запросы. В более новых версиях SQLite ROLLBACK будет продолжен, а ожидающие команды часто будут прерваны, что приведет к возврату ошибки SQLITE_ABORT или SQLITE_ABORT_ROLLBACK. В SQLite версии 3.8.8 (2015-01-16) и более поздних версиях ожидающий процесс чтения продолжит функционировать после ROLLBACK, пока ROLLBACK не изменит схему базы данных.

Если PRAGMA journal_mode установлено в OFF (что приводит к отключению файла журнала отката), то поведение команды ROLLBACK неопределенно.

3. Обработка ошибок в рамках транзакции

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

  • SQLITE_FULL: база данных или диск заполнены
  • SQLITE_IOERR: ошибка ввода-вывода на диске
  • SQLITE_BUSY: база данных используется другим процессом
  • SQLITE_NOMEM: недостаточно памяти

Во всех этих случаях SQLite пытается отменить только команду, с которой работало, и оставить изменения от предыдущих команд в той же транзакции нетронутыми, продолжая транзакцию. Однако в зависимости от оцениваемой команды и момента возникновения ошибки SQLite может потребоваться откатить и отменить всю транзакцию. Приложение может определить, какой курс действий выбрало SQLite, используя интерфейс языка C sqlite3_get_autocommit().

Рекомендуется, чтобы приложения реагировали на перечисленные выше ошибки, явно выполняя команду ROLLBACK. Если транзакция уже была автоматически откатана в ответ на ошибку, то команда ROLLBACK завершится ошибкой, но это не нанесёт вреда.

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

Эта страница была последняя раз изменена 2023-03-14 14:31:07 UTC

SQLite is in the Public Domain.
https://sqlite.org/lang_transaction.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API