Что такое rollback в транзакциях и зачем он нужен
Что проверяют
Понимаете ли вы атомарность не на уровне определения, а в коде: где открывается транзакция, кто решает её откатить и что при этом реально отменяется. Следом почти всегда спрашивают про @Transactional: при каких исключениях Spring делает откат.
Как отвечать
Rollback отменяет все изменения текущей транзакции и возвращает данные к состоянию до её начала. Это механизм атомарности из ACID: перевод денег либо проходит целиком, либо не проходит вовсе.
В чистом JDBC транзакцией управляете вы сами:
setAutoCommit(false): по умолчанию каждый запрос коммитится сразу, и откатывать нечего;commit()иrollback(): вызываются явно, откат обычно вcatch;Savepoint: частичный откат черезrollback(savepoint), сама транзакция при этом продолжается.
В Spring это делает прокси @Transactional. По умолчанию откат идёт только на непроверяемых исключениях (RuntimeException и Error), а на checked транзакция коммитится. Поведение меняется через rollbackFor и noRollbackFor. Вручную пометить транзакцию на откат можно через TransactionAspectSupport.currentTransactionStatus().setRollbackOnly().
Хорошо показать, что происходит в базе: в InnoDB изменения откатываются по undo log, а в PostgreSQL за счёт MVCC транзакция просто помечается прерванной, и её версии строк становятся невидимыми.
Где спотыкаются
Ловят исключение внутри метода и не пробрасывают дальше. Spring видит нормальный выход и делает commit, хотя половина операций не прошла.
Вызывают @Transactional-метод из того же класса через this. Вызов идёт мимо прокси, транзакции нет. Похожая ловушка: внутренний метод с REQUIRED помечает общую транзакцию на откат, внешний глотает исключение и получает UnexpectedRollbackException при коммите.
Считают, что rollback отменяет всё. Отправленное письмо, сообщение в Kafka или вызов внешнего API он не вернёт, как и значение последовательности в PostgreSQL. Для таких случаев нужны transactional outbox или саги.