Транзакции: BEGIN, COMMIT, ROLLBACK

Объединяем несколько изменений в одну неделимую операцию.

Транзакция — это группа операций, которая выполняется по принципу «всё или ничего»: либо применяются все изменения, либо ни одного.

Зачем нужны транзакции

Классический пример — перевод денег: списать у одного, зачислить другому. Это две операции, но они должны выполниться вместе. Если после списания случится сбой, а зачисление не произойдёт, деньги «исчезнут». Транзакция гарантирует, что либо обе операции применятся, либо ни одна — это свойство атомарности, первая буква в ACID.

BEGIN ... COMMIT — применить всё

Транзакцию открывают командой BEGIN, а завершают COMMIT — в этот момент все изменения внутри становятся постоянными. Переведём 300 рублей от Ани Борису:

CREATE TABLE accounts (id INTEGER PRIMARY KEY, name TEXT, balance INTEGER);

INSERT INTO accounts (name, balance) VALUES ('Аня', 1000), ('Борис', 500);

BEGIN;
UPDATE accounts SET balance = balance - 300 WHERE name = 'Аня';
UPDATE accounts SET balance = balance + 300 WHERE name = 'Борис';
COMMIT;

SELECT name, balance FROM accounts;

Вывод:

Аня|700
Борис|800

Оба обновления применились как единое целое. После COMMIT изменения зафиксированы в файле базы.

ROLLBACK — отменить всё

Если внутри транзакции что-то пошло не так, выполняют ROLLBACK — и база возвращается в состояние до BEGIN, будто ничего не было. Изменим баланс, но откатим:

CREATE TABLE accounts (id INTEGER PRIMARY KEY, name TEXT, balance INTEGER);

INSERT INTO accounts (name, balance) VALUES ('Аня', 1000);

BEGIN;
UPDATE accounts SET balance = 0 WHERE name = 'Аня';
ROLLBACK;

SELECT name, balance FROM accounts;

Вывод:

Аня|1000

Несмотря на UPDATE ... SET balance = 0, после ROLLBACK баланс остался прежним — 1000. Изменение откатилось.

Транзакции и производительность

У транзакций есть приятный побочный эффект. По умолчанию каждая отдельная команда — это своя маленькая транзакция, и SQLite после каждой записывает данные на диск. Если нужно вставить тысячи строк, оберните их в одну транзакцию BEGIN ... COMMIT — диск тронется один раз, и вставка ускорится во много раз. Это стандартный приём массовой загрузки данных в SQLite.

Итог

  • Транзакция — это «всё или ничего»: BEGIN открывает, COMMIT фиксирует, ROLLBACK отменяет.
  • Атомарность защищает связанные операции (например, перевод денег) от частичного применения.
  • Оборачивание массовых вставок в одну транзакцию резко ускоряет запись.
Проверьте себя
1. Что гарантирует транзакция?
AЧто запрос выполнится быстрее
BЧто группа операций применится целиком или не применится вовсе
CЧто данные зашифруются
DЧто таблица будет проиндексирована
2. Что произойдёт с изменениями после ROLLBACK?
AОни зафиксируются
BОни отменятся, база вернётся в состояние до BEGIN
CОни применятся частично
DБаза будет повреждена
3. Зачем оборачивать тысячи INSERT в одну транзакцию?
AЧтобы они выполнились в случайном порядке
BЧтобы резко ускорить вставку: запись на диск произойдёт один раз
CЧтобы включить индексы
DЭто обязательное требование SQLite
Поддержать проект