CodeRang
Темы SQL

Транзакции SQL: BEGIN, COMMIT, ROLLBACK и изоляция

Транзакции SQL объединяют несколько операций в единое логическое изменение данных. Разберём BEGIN, COMMIT и ROLLBACK, а также то, как изоляция влияет на параллельные транзакции.

Обновлено · Команда SQL Arena

Что потренируете

  • Объединять связанные изменения между BEGIN и COMMIT
  • Делать ROLLBACK при ошибке до фиксации
  • Понимать уровни изоляции и типовые аномалии
  • Блокировать нужные строки через SELECT FOR UPDATE
  • Проверять итоговое состояние после атомарной операции

Пример задачи в тренажёре

Так выглядит задача в SQL Arena: условие, редактор, результат и схема базы.

Пред.След.Случайная
ЗаданиеОтправкиAI Mentor
Проверьте балансы после перевода

До перевода у Alice было 1200 USD, у Bruno — 700 USD. В одной транзакции 250 USD списали со счёта Alice и зачислили Bruno; записи операции сохранены в ledger_entries. Выведите owner_name, balance, currency для счетов 1, 2 и 3 в порядке id, чтобы проверить итоговое состояние.

Запрос 1PostgreSQLv16
SELECT owner_name, balance, currency
FROM accounts
WHERE id IN (1, 2, 3)
ORDER BY id;
Отправить
Результатaccountsledger_entries
Ответ принят

Как работают транзакции SQL на примере

Сам SELECT в примере — финальная проверка уже выполненной операции. Он показывает Alice с 950 USD и Bruno с 950 USD: сумма между этими двумя счетами не изменилась, изменилось только распределение денег. Clara попадает в результат как контрольная строка и остаётся с прежним балансом 430 USD. ORDER BY id нужен, чтобы проверка всегда возвращала строки в одном порядке.

Ключевой смысл находится в том, как такие данные должны меняться. Списание 250 и зачисление 250 должны быть внутри одной транзакции: BEGIN открывает её, оба UPDATE выполняются до фиксации, COMMIT делает изменения видимыми как завершённую операцию. Если второе изменение или проверка завершается ошибкой, ROLLBACK должен отменить и первое. Иначе база может получить половинчатый перевод.

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

В PostgreSQL типичный инструмент для такого сценария — SELECT ... FOR UPDATE. Он блокирует выбранную строку до конца транзакции, поэтому другая конкурирующая операция не сможет изменить тот же счёт как будто блокировки нет. При переводе между двумя счетами полезно брать блокировки в стабильном порядке, например по id, чтобы снизить риск взаимных блокировок. После этого условия вроде достаточного баланса проверяются уже на защищённом состоянии.

Уровень изоляции транзакции определяет, какие изменения параллельных операций она может видеть и какие аномалии допускаются. В стандарте SQL выделяют READ UNCOMMITTED, READ COMMITTED, REPEATABLE READ и SERIALIZABLE, но фактическое поведение зависит от СУБД. Чем сильнее изоляция, тем больше гарантий согласованности, однако это может повышать стоимость конкурирующих операций. Для практики важно различать атомарность транзакции и изоляцию: COMMIT или ROLLBACK отвечают за фиксацию целого набора изменений, а уровень изоляции — за взаимодействие одновременных транзакций.

SQLPostgreSQL v16
SELECT owner_name, balance, currency
FROM accounts
WHERE id IN (1, 2, 3)
ORDER BY id;
Результат запроса
owner_namebalancecurrency
Alice950USD
Bruno950USD
Clara430USD

Ошибки в SQL-транзакциях и изоляции

01

COMMIT после частично выполненной операции

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

02

Проверка баланса без защиты от конкуренции

Условие balance >= amount само по себе не гарантирует безопасность, если параллельные транзакции читают одно и то же старое значение. Нужна атомарная операция, подходящий уровень изоляции или блокировка строки.

03

FOR UPDATE берёт строки в случайном порядке

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

Задачи по теме в тренажёре

Трек «SQL для Backend-разработчика»

В SQL Arena задачи на транзакции сделаны как сценарии, где нужно сохранить инвариант под ошибками и конкуренцией. Есть упражнения на безопасное списание товара, перевод без овердрафта, конкурентное списание со счёта, защиту счётчика от потерянных инкрементов, очередь pending-задач и бронирование места только один раз. Эти задачи относятся к Premium. Если хотите собрать тему в более широкий backend-контекст, переходите в трек «SQL для Backend-разработчика». В SQL Arena 1 192 задачи, а решения проверяются на скрытых данных. Для PostgreSQL, MySQL, ClickHouse и BigQuery есть отдельные песочницы в браузере. В режиме «Собеседование» работает серверный таймер, подсказки отключены, после сессии доступен отчёт; бесплатно режим можно запускать один раз в день. AI-ментор умеет объяснять ошибки и давать подсказки, бесплатно доступно 10 обращений всего.

Частые вопросы

Что такое транзакции SQL?

Транзакция SQL объединяет несколько операций в одну логическую единицу работы. Изменения можно зафиксировать через COMMIT или отменить через ROLLBACK, если операция не должна завершаться.

Как работают BEGIN, COMMIT и ROLLBACK в SQL?

BEGIN начинает явную транзакцию, после чего выполняются связанные запросы. COMMIT фиксирует их результат, а ROLLBACK отменяет изменения текущей транзакции, которые ещё не были зафиксированы.

Что такое изоляция транзакций SQL?

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

Какие уровни изоляции есть в SQL?

Стандарт SQL определяет READ UNCOMMITTED, READ COMMITTED, REPEATABLE READ и SERIALIZABLE. Реализация и конкретные гарантии этих уровней могут отличаться между СУБД.

Когда нужен ROLLBACK в SQL-транзакции?

ROLLBACK нужен, когда изменения внутри текущей транзакции требуется отменить до их фиксации. Например, это полезно, если одна из связанных операций завершилась ошибкой и весь набор изменений должен остаться неприменённым.

Практика транзакций SQL

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

Практиковать транзакции в SQL Arena