Транзакция
1. Синтаксис управления транзакциями
2. Транзакции
Чтение и запись не выполняются вне транзакции. Любая команда, обращающаяся к базе данных (то есть практически любая команда SQL, за исключением нескольких операторов PRAGMA), автоматически начинает транзакцию, если она ещё не активна. Автоматически начатые транзакции фиксируются после завершения последнего оператора SQL.
Транзакции можно начинать вручную с помощью команды BEGIN. Такие транзакции обычно продолжаются до следующей команды COMMIT или ROLLBACK. Однако транзакция также будет отменена командой ROLLBACK, если база данных будет закрыта или произойдёт ошибка и указан алгоритм разрешения конфликтов ROLLBACK. Дополнительные сведения об алгоритме разрешения конфликтов ROLLBACK см. в документации по предложению ON CONFLICT.
END TRANSACTION является синонимом COMMIT.
Транзакции, созданные с помощью BEGIN...COMMIT, не могут быть вложенными. Для вложенных транзакций используйте команды SAVEPOINT и RELEASE. Предложение "TO SAVEPOINT name" команды ROLLBACK, показанной на синтаксической диаграмме выше, применимо только к транзакциям 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 тем, что транзакция записи начинается немедленно. В режиме WAL EXCLUSIVE и IMMEDIATE эквивалентны, но в других режимах ведения журнала EXCLUSIVE не позволяет другим подключениям к базе данных читать её, пока выполняется транзакция.
2.3. Неявные и явные транзакции
Неявная транзакция (транзакция, которая начинается автоматически, а не командой BEGIN) фиксируется автоматически после завершения последнего активного оператора. Оператор завершается, когда закрывается его последний курсор; это гарантированно происходит при сбросе или финализации подготовленного оператора. Некоторые операторы могут «завершиться» с точки зрения управления транзакциями до сброса или финализации, но это не гарантируется. Единственный способ убедиться, что оператор «завершён», — вызвать для него sqlite3_reset() или sqlite3_finalize(). Открытый объект sqlite3_blob, используемый для инкрементального ввода-вывода BLOB, также считается незавершённым оператором. Объект sqlite3_blob завершает работу при его закрытии.
Явная команда 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_INTERRUPT: операция прервана вызовом sqlite3_interrupt() или аналогичным способом.
- SQLITE_NOMEM: недостаточно памяти
При всех этих ошибках SQLite пытается отменить только оператор, над которым выполнялась работа, сохранить изменения предыдущих операторов в той же транзакции и продолжить транзакцию. Однако, в зависимости от выполняемого оператора и момента возникновения ошибки, SQLite может потребоваться отменить всю транзакцию. Приложение может определить, какой вариант выбрала SQLite, с помощью интерфейсов языка C sqlite3_get_autocommit() или sqlite3_txn_state().
Приложение может обработать перечисленные выше ошибки, явно выполнив команду ROLLBACK. В этом случае состояние транзакции после любой из этих ошибок всегда будет одинаковым. Если транзакция уже была автоматически отменена в ответ на ошибку, команда ROLLBACK завершится ошибкой, но это не причинит вреда.
В будущих версиях SQLite список ошибок, способных вызвать автоматическую отмену транзакции, может быть расширен. Реакция на ошибки в будущих версиях SQLite может измениться. В частности, в будущих версиях SQLite мы можем упростить интерфейс, заставив перечисленные выше ошибки всегда безусловно отменять транзакцию.
Эта страница обновлена 2026-02-18 11:56:50Z
SQLite is in the Public Domain.
https://sqlite.org/lang_transaction.html