Транзакция в базе данных — набор SQL-операций, которые выполняются как единое целое по принципу «всё или ничего»: либо все изменения фиксируются командой COMMIT, либо полностью отменяются через ROLLBACK. Надёжность транзакций определяется четырьмя гарантиями — моделью ACID.
В статье разберём, что такое транзакция в СУБД, как работают команды BEGIN, COMMIT, ROLLBACK и SAVEPOINT, какие уровни изоляции защищают данные при параллельном доступе и как всё это реализовано в PostgreSQL.
Учитесь бесплатно за счёт государства
Экономия до 100 000 ₽ на любой программе
Транзакция в базе данных — логически завершённая единица работы, которая переводит БД из одного согласованного состояния в другое. SQL-транзакция объединяет одну или несколько DML-операций (INSERT, UPDATE, DELETE) и гарантирует два исхода: COMMIT — все изменения зафиксированы в БД, или ROLLBACK — все изменения отменены, БД возвращается в исходное состояние.
СУБД считает набор операций неделимым. Если в процессе выполнения происходит сбой или нарушение ограничения целостности, система автоматически откатывает всё, что было сделано в рамках этой транзакции.
Классический сценарий — банковский перевод. Нужно выполнить два UPDATE: списать сумму с одного счёта и зачислить на другой.
BEGIN;
UPDATE accounts SET balance = balance — 5000 WHERE id = 1;
UPDATE accounts SET balance = balance + 5000 WHERE id = 2;
COMMIT;
Без транзакции в БД опасность очевидна: если первый UPDATE выполнен, а второй завершился ошибкой — деньги спишутся, но не зачислятся. Транзакция исключает такой исход: при ошибке СУБД автоматически откатит первое изменение через ROLLBACK.
Атомарность транзакции означает, что в базе не остаётся «полувыполненных» операций — либо оба UPDATE применились, либо ни один.
Транзакция в БД решает три задачи:
Целостность данных через транзакции критична в банкинге и финансовых платформах, интернет-магазинах (списание товара + создание заказа), ERP-системах и складском учёте. Простыми словами: транзакция в БД — это страховка от неполных изменений в любой многошаговой операции.

ACID определяет четыре стандартных свойства транзакций в базе данных, которые СУБД должна гарантировать:
ACID реализуется через механизмы СУБД: блокировки, многоверсионный доступ к данным и журнал транзакций.
Атомарность гарантирует: если хотя бы одна операция транзакции завершилась с ошибкой, все предыдущие изменения откатываются через ROLLBACK. Пример нарушения без транзакции: UPDATE на списание выполнен, но UPDATE на зачисление упал с ошибкой внешнего ключа — баланс уменьшился, но деньги не поступили. Транзакция исключает этот сценарий.
Согласованность означает, что транзакция переводит базу из одного валидного состояния в другое. Валидность проверяется через ограничения целостности: внешние ключи (FOREIGN KEY), условия (CHECK), уникальность (UNIQUE). Если ограничение нарушено — ACID-транзакция откатится, не допустив некорректного состояния БД.
Изолированность означает, что параллельные транзакции не влияют на результаты друг друга. Степень изолированности задаётся уровнями изоляции — от минимальной (Read Uncommitted) до максимальной (Serializable). Именно изолированность управляется через уровни изоляции транзакций, которые разбираются в отдельном разделе.
Долговечность гарантирует: после успешного COMMIT изменения сохраняются в БД даже при отказе питания или краше сервера. Долговечность обеспечивается журналом транзакций — специальным файлом, куда СУБД записывает все DML-операции до подтверждения. При восстановлении система дочитывает журнал и воспроизводит незавершённые фиксации.

Три базовые команды управляют жизненным циклом транзакции в базе данных:
BEGIN инициирует явную транзакцию. Всё, что выполняется после BEGIN до COMMIT или ROLLBACK, является частью этой транзакции.
BEGIN;
UPDATE cars SET max_speed = 240 WHERE id = 1;
— Внутри транзакции изменение видно текущему сеансу:
SELECT max_speed FROM cars WHERE id = 1; — вернёт 240
COMMIT;
— После COMMIT данные зафиксированы для всех сеансов:
SELECT max_speed FROM cars WHERE id = 1; — вернёт 240
COMMIT фиксирует изменения постоянно. После COMMIT отменить их командой ROLLBACK уже невозможно — данные записаны в БД и видны всем пользователям.
ROLLBACK отменяет все операции транзакции с начала BEGIN, возвращая базу в исходное состояние. Выполняется как вручную, так и автоматически при ошибке внутри транзакции.
BEGIN;
UPDATE cars SET max_speed = 300 WHERE id = 1;
ROLLBACK;
— Изменение полностью отменено:
SELECT max_speed FROM cars WHERE id = 1; — вернёт исходное значение
Откат изменений через ROLLBACK полный: ни одно из DML-изменений транзакции не попадает в БД. Без BEGIN вернуть UPDATE невозможно — без явной транзакции запрос уже зафиксирован автоматически.
SAVEPOINT создаёт именованную точку внутри транзакции. ROLLBACK TO откатывает только изменения после этой точки, сохраняя все предыдущие операции. Вся транзакция при этом продолжает выполняться.
BEGIN;
UPDATE orders SET status = ‘processing’ WHERE id = 100;
SAVEPOINT after_status;
UPDATE inventory SET stock = stock — 1 WHERE product_id = 5;
— Что-то пошло не так — откатываем только складскую операцию:
ROLLBACK TO after_status;
— Статус заказа сохранён, изменение склада отменено:
COMMIT;
После ROLLBACK TO after_status обновление склада отменяется, но статус заказа остаётся processing. COMMIT фиксирует только изменение статуса. Точки сохранения поддерживают PostgreSQL, Oracle и MySQL. SAVEPOINT позволяет реализовать частичный откат транзакции — без отмены всей транзакции целиком.

В SQL различают четыре типа транзакций:
| Тип |
Управление |
Применение |
|---|---|---|
| Явная | Начинается с BEGIN, завершается COMMIT / ROLLBACK вручную | Многошаговые операции с полным контролем |
| Неявная | Запускается автоматически при DML; требует явного COMMIT / ROLLBACK | SQL Server при IMPLICIT_TRANSACTIONS=ON |
| Вложенная | BEGIN внутри BEGIN; реально контролируется только внешней транзакцией | Процедуры и вызовы подмодулей |
| Автономная | Независима от вызывающей транзакции | Логирование ошибок, аудит |
Отдельно стоит режим автофиксации (autocommit): каждый одиночный SQL-запрос автоматически оборачивается в транзакцию с немедленным COMMIT. Именно поэтому UPDATE без BEGIN нельзя откатить — он уже зафиксирован до того, как вы успели вызвать ROLLBACK.
Явная транзакция — самый распространённый тип: разработчик пишет BEGIN + COMMIT/ROLLBACK вручную и получает полный контроль над многошаговыми операциями.
В PostgreSQL по умолчанию включён режим автофиксации: каждый запрос вне явной транзакции сразу фиксируется. Это причина, почему одиночный UPDATE без BEGIN нельзя откатить — СУБД уже выполнила COMMIT автоматически. BEGIN отключает autocommit до завершения текущей транзакции.
Неявная транзакция используется в SQL Server при включённом параметре IMPLICIT_TRANSACTIONS=ON: DML-запрос запускает транзакцию автоматически, но завершение требует явного COMMIT или ROLLBACK от разработчика.
Вложенная транзакция в SQL возникает, когда BEGIN выполняется внутри уже открытой транзакции. Внутренний COMMIT не фиксирует данные немедленно — изменения сохраняются только при завершении внешней транзакции. Если внешняя откатывается, откатываются и все вложенные изменения: только внешняя транзакция реально управляет исходом.
Автономная транзакция полностью независима от вызывающей. COMMIT или ROLLBACK внутри автономной транзакции не влияет на исход родительской — и наоборот. Применяется для записи событий в журнал аудита или логирования ошибок: запись сохраняется, даже если основная транзакция откатилась.

При параллельном доступе нескольких транзакций к одним данным возникают аномалии данных. Их пять, и каждый феномен конкурентного доступа возникает при недостаточной изоляции транзакций.
Феномены по возрастанию серьёзности:
Потерянное обновление (lost update): транзакция Б перезаписывает изменения, которые внесла транзакция А, не зная об этих изменениях. Результат — обновление А «потеряно». Предотвращается блокировкой строки на запись начиная с уровня Read Committed.
Грязное чтение (dirty read): транзакция читает незафиксированные изменения другой транзакции. Если та откатывается — читающая транзакция использовала данные, которых в БД никогда не существовало. Грязное чтение предотвращается уровнем Read Committed. В PostgreSQL оно технически невозможно даже на уровне Read Uncommitted — механизм многоверсионного доступа (MVCC) исключает чтение незафиксированных данных.
Неповторяющееся чтение: транзакция дважды читает одну и ту же строку и получает разные значения, потому что другая транзакция успела изменить или удалить эту строку между двумя SELECT. Предотвращается уровнем Repeatable Read.
Фантомное чтение (phantom read): транзакция дважды выполняет одинаковый запрос с условием, но во второй раз получает дополнительные строки — их добавила другая транзакция. Ключевое отличие от неповторяющегося чтения: меняется не значение строки, а их количество. По стандарту SQL фантомное чтение предотвращается уровнем Serializable. В PostgreSQL уровень Repeatable Read также защищает от фантомного чтения — это расширение стандарта.
Аномалия сериализации (serialization anomaly) возникает, когда результат параллельного выполнения транзакций не совпадает ни с одним вариантом их последовательного выполнения.
Пример: транзакция Т1 меняет запись Toyota → BMW, транзакция Т2 одновременно меняет BMW → Toyota. При любой последовательности (Т1 затем Т2 или Т2 затем Т1) итоговое значение будет Toyota. Но при параллельном выполнении обе видят исходные данные и обе применяют изменения — итог невозможен ни при каком последовательном запуске.
Аномалия сериализации предотвращается только уровнем Serializable.
Уровень изоляции транзакции определяет допустимые феномены параллельного доступа. Чем выше уровень — тем строже изоляция и тем ниже производительность при высокой конкурентности.
Установка уровня изоляции в PostgreSQL:
BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ;
Матрица феноменов и уровней изоляции транзакций в СУБД:
| Уровень изоляции |
Потерянное обновление |
Грязное чтение |
Неповт. чтение |
Фантомное чтение |
Аном. сериализации |
|---|---|---|---|---|---|
| Read Uncommitted | ✓ | ✓* | ✓ | ✓ | ✓ |
| Read Committed | ✗ | ✗ | ✓ | ✓ | ✓ |
| Repeatable Read | ✗ | ✗ | ✗ | ✓** | ✓ |
| Serializable | ✗ | ✗ | ✗ | ✗ | ✗ |
| Snapshot (MVCC) | ✗ | ✗ | ✗ | ✗*** | ✓ |
Хотите сменить профессию или повысить квалификацию?
Федеральный проект «Активные меры содействия занятости» даёт возможность пройти обучение бесплатно за счёт государства
✓ — феномен возможен; ✗ — предотвращён. * В PostgreSQL Read Uncommitted = Read Committed: MVCC исключает грязное чтение. ** В PostgreSQL Repeatable Read также предотвращает фантомное чтение. *** Snapshot предотвращает фантомное чтение, но не аномалию сериализации без SSI.

Read Uncommitted — самый слабый уровень. По стандарту SQL допускает грязное чтение. В PostgreSQL этот уровень технически работает как Read Committed: многоверсионная модель параллельного доступа (MVCC) делает грязное чтение физически невозможным — читатель всегда получает снимок зафиксированных данных.
Read Committed — уровень изоляции по умолчанию в PostgreSQL и SQL Server. При каждом SELECT создаётся новый снимок зафиксированных данных. Транзакция не видит незафиксированных изменений, но при повторном чтении той же строки может получить другой результат — если другая транзакция успела выполнить COMMIT между двумя запросами.
На уровне Repeatable Read снимок базы данных создаётся один раз — при первом запросе после BEGIN — и транзакция работает с ним до завершения. Повторное чтение той же строки всегда вернёт одинаковый результат.
В PostgreSQL этот уровень дополнительно предотвращает фантомное чтение — поведение, которого стандарт SQL не требует. При конкурентном обновлении одной строки двумя транзакциями PostgreSQL вернёт ошибку:
ERROR: could not serialize access due to concurrent update
В этом случае транзакцию необходимо повторить.
Serializable — максимальный уровень изоляции транзакций. Снимок создаётся сразу после BEGIN, и СУБД гарантирует: результат параллельного выполнения идентичен какому-либо последовательному. При конфликтах возникает ошибка сериализации, и транзакцию нужно повторить. Serializable предотвращает все пять феноменов, но снижает производительность при высокой нагрузке.
Snapshot через механизм многоверсионного доступа (MVCC) даёт каждой транзакции собственный снимок данных на момент начала. Ключевое преимущество: читатели не блокируют писателей, и наоборот. PostgreSQL использует MVCC для реализации всех уровней изоляции — именно это объясняет его поведение на уровне Read Uncommitted.

PostgreSQL полностью поддерживает ACID, а параллельность реализует через механизм многоверсионного доступа (MVCC). Для практической работы с транзакциями в PostgreSQL используется инструмент psql — интерактивная командная строка:
sudo -u postgres psql postgres
Далее — два практических примера управления транзакциями в PostgreSQL.
Создадим тестовую таблицу и проверим полный цикл транзакции:
— Создаём тестовую таблицу
CREATE TABLE cars (id SERIAL PRIMARY KEY, model VARCHAR(50), max_speed INT);
INSERT INTO cars (model, max_speed) VALUES (‘Toyota’, 180);
— Пример с ROLLBACK:
BEGIN;
UPDATE cars SET max_speed = 250 WHERE id = 1;
— Внутри транзакции текущий сеанс видит незафиксированное изменение:
SELECT max_speed FROM cars WHERE id = 1; — 250
ROLLBACK;
— После ROLLBACK данные не изменились:
SELECT max_speed FROM cars WHERE id = 1; — 180
— Пример с COMMIT:
BEGIN;
UPDATE cars SET max_speed = 220 WHERE id = 1;
COMMIT;
— После COMMIT изменение зафиксировано для всех сеансов:
SELECT max_speed FROM cars WHERE id = 1; — 220
Ключевой момент: внутри транзакции PostgreSQL показывает собственные незафиксированные изменения текущему сеансу. Другие сеансы на уровне Read Committed увидят значение 180 до тех пор, пока не будет выполнен COMMIT.
Пример транзакции в БД с частичным откатом — обновление заказа и склада:
BEGIN;
— Шаг 1: обновляем статус заказа
UPDATE orders SET status = ‘processing’ WHERE id = 100;
— Создаём точку сохранения после успешного шага
SAVEPOINT after_status;
— Шаг 2: списываем товар со склада
UPDATE inventory SET stock = stock — 1 WHERE product_id = 5;
— Что-то пошло не так — откатываем только шаг 2:
ROLLBACK TO after_status;
— Шаг 1 (статус заказа) сохранён, шаг 2 (склад) отменён:
COMMIT;
После ROLLBACK TO after_status обновление склада отменяется, но статус заказа остаётся processing. COMMIT фиксирует только изменение статуса. Частичный откат транзакции через SAVEPOINT в PostgreSQL позволяет не терять уже выполненную работу при ошибке в одном из шагов.

При параллельной работе с базой данных транзакции сталкиваются с тремя типовыми проблемами: взаимная блокировка (deadlock), переполнение журнала транзакций и ошибка сериализации. Каждая требует отдельной стратегии обработки.
Взаимная блокировка в базе данных — ситуация, когда две транзакции взаимно ждут ресурсов, заблокированных друг другом, и ни одна не может продолжить выполнение.
| Шаг |
Транзакция А |
Транзакция Б |
|---|---|---|
| 1 | Блокирует строку 1 | Блокирует строку 2 |
| 2 | Ожидает строку 2 | Ожидает строку 1 |
| 3 | ← взаимная блокировка → | ← взаимная блокировка → |
СУБД обнаруживает дедлок через граф ожидания: если граф содержит цикл, система выбирает транзакцию-«жертву» и откатывает её. Приложение должно перехватывать эту ошибку и повторять транзакцию.
Три правила профилактики взаимных блокировок:

Журнал транзакций — файл, куда СУБД записывает все DML-операции до COMMIT или ROLLBACK. Он обеспечивает букву D в ACID: зафиксированные данные не теряются при сбое, а незафиксированные изменения можно откатить при любом исходе.
Три функции журнала транзакций:
Переполнение журнала возникает при долгих транзакциях, отсутствии резервного копирования или нехватке места на диске. В SQL Server предусмотрены три режима работы журнала: SIMPLE (автоочистка после резервного копирования БД), FULL (полный контроль, обязателен регулярный backup журнала), BULK_LOGGED (компромисс для массовых операций).
Профилактика переполнения: регулярное резервное копирование журнала транзакций, короткие транзакции и мониторинг размера файла журнала.

Хотите освоить работу с базами данных и стать аналитиком данных? В рамках федерального проекта «Активные меры содействия занятости» доступно обучение по программе «Специалист по аналитике и базам данных в информационных системах» — с нуля, онлайн, без затрат. Смотрите каталог доступных программ.
Транзакция — набор SQL-операций, которые СУБД выполняет как единое действие: либо все изменения применяются и фиксируются (COMMIT), либо ни одно не сохраняется (ROLLBACK). Классический пример — банковский перевод: списание с одного счёта и зачисление на другой должны произойти вместе или не произойти вовсе.
ACID — четыре гарантии надёжных транзакций: Atomicity (атомарность — всё или ничего), Consistency (согласованность — БД переходит между валидными состояниями), Isolation (изолированность — транзакции не мешают друг другу), Durability (долговечность — зафиксированные данные сохраняются при сбое). Реализуются через механизмы СУБД: блокировки, MVCC, журнал транзакций.
COMMIT окончательно сохраняет все изменения транзакции в базе данных. ROLLBACK отменяет все незафиксированные изменения с момента BEGIN, возвращая базу в исходное состояние. После COMMIT отменить изменения через ROLLBACK невозможно — данные уже зафиксированы.
Да — через команду SAVEPOINT. Создайте точку сохранения внутри транзакции (SAVEPOINT name), а при необходимости выполните ROLLBACK TO name. Это отменит изменения только после точки, сохранив более ранние операции. Вся транзакция завершается обычным COMMIT. Полный пример с кодом — в разделе «Пример с SAVEPOINT в PostgreSQL».
Без BEGIN каждый запрос выполняется в режиме автофиксации (autocommit) — автоматически оборачивается в отдельную транзакцию и немедленно фиксируется. Это значит: одиночный UPDATE без BEGIN нельзя откатить, он уже зафиксирован. BEGIN позволяет объединить несколько операций в одну транзакцию с явным контролем COMMIT и ROLLBACK.
Каждый уровень определяет допустимые аномалии параллельного доступа. Read Committed (по умолчанию в PostgreSQL) предотвращает грязное чтение. Repeatable Read добавляет защиту от неповторяющегося чтения. Serializable устраняет все феномены, включая аномалию сериализации — самый строгий и медленный уровень. Матрица феноменов и уровней — в разделе «Уровни изоляции транзакций».
Три правила профилактики: первое — всегда обращайтесь к таблицам и строкам в одном порядке во всех транзакциях; второе — минимизируйте длительность транзакций, чем короче, тем меньше вероятность конфликта; третье — не удерживайте блокировки во время ожидания ввода пользователя или внешних запросов.
PostgreSQL реализует многоверсионную модель параллельного доступа (MVCC), при которой читатели всегда видят снимок зафиксированных данных. Грязное чтение технически невозможно в этой архитектуре — читатель получает версию данных на момент запроса, не видя незафиксированных изменений других транзакций.
Вложенная транзакция (BEGIN внутри BEGIN) контролируется только внешней: внутренний COMMIT не фиксирует данные до завершения внешней, откат внешней отменяет и внутренние изменения. Автономная транзакция полностью независима — её COMMIT/ROLLBACK не зависит от исхода вызывающей. Применяется для аудита и логирования ошибок.
Serializable необходим, когда результат параллельного выполнения должен быть идентичен последовательному — финансовые операции, бухгалтерский учёт, системы инвентаризации. Из-за возможных ошибок сериализации и повторных попыток применяйте его только там, где строгая согласованность данных важнее производительности.
Подайте заявку —
забронируйте место в группе
45 000 мест на 2026 год. Бесплатное обучение по федеральному проекту «Активные меры содействия занятости»