Транзакции в SQLite: просто, но со своими нюансами (Мини-гайд)

GuDron

dumpz.ws
Admin
Регистрация
28 Янв 2020
Сообщения
9,447
Реакции
1,547
Credits
33,142
Транзакции в SQLite: просто, но со своими нюансами.

SQLite — это встраиваемая база данных, и она немного отличается от привычных серверных СУБД (PostgreSQL, MySQL) в части работы с транзакциями. Но транзакции там есть, и работают по принципу ACID — атомарность, согласованность, изолированность и долговечность.

Разберёмся по полочкам:
Как начинается и заканчивается транзакция?
SQL:
BEGIN TRANSACTION;
-- какие-то запросы
COMMIT;
Или, в случае ошибки:
SQL:
ROLLBACK;
Можно использовать синонимы:
- BEGIN = BEGIN DEFERRED
- BEGIN IMMEDIATE
- BEGIN EXCLUSIVE

Они отличаются уровнем блокировок.

Типы транзакций

1. DEFERRED (по умолчанию) -
Блокировки ставятся только при первом доступе к таблице (на чтение/запись).

2. IMMEDIATE - Сразу ставит блокировку на запись (write-lock). Полезно, если точно знаешь, что будешь писать — исключишь гонки.

3. EXCLUSIVE - Блокирует БД полностью. Даже другие чтения не пройдут.


Особенности SQLite
- Одна запись за раз: SQLite поддерживает одновременные чтения, но только одну запись одновременно. Остальные получат "database is locked".
- Авто-коммиты: если явно не начать транзакцию — SQLite будет делать коммит после каждого запроса.
- Журналирование: SQLite использует WAL (write-ahead log) или rollback journal — в зависимости от настроек. WAL — более производителен для параллельного чтения.

Советы

- При пакетной вставке всегда оборачивай в транзакцию:
SQL:
BEGIN;
INSERT INTO users VALUES (...);
INSERT INTO users VALUES (...);
...
COMMIT;
→ Это в разы быстрее, чем отдельные INSERT с автокоммитом.

- Если получаешь ошибку database is locked, проверь:
- Не оставил ли ты открытые транзакции
- Не работают ли несколько процессов с БД одновременно без координации

Вывод: транзакции в SQLite — простые, но критически важные для производительности и корректности. Даже в одиночной БД нужна дисциплина.