Писали ли транзакции в SQL
Что проверяют
Понимаете ли вы, где на самом деле начинается и заканчивается транзакция в приложении на Spring, и что аннотация это не заклинание. Вопрос звучит про SQL, но отвечать придётся про то, как с ним работает ваш код.
Как отвечать
Коротко про суть: транзакция переводит базу из одного согласованного состояния в другое целиком либо не выполняется вовсе. Дальше про изоляцию: грязное чтение, неповторяющееся чтение, фантомы и какой уровень стоит по умолчанию в вашей базе. В PostgreSQL это Read Committed, в InnoDB уровень строже.
Потом про Spring, потому что спрашивают именно об этом:
@Transactionalработает через прокси, границу ставят на сервисном слое;- откат по умолчанию происходит на непроверяемых исключениях, для проверяемого нужен явный
rollbackFor; readOnlyи правила распространения задают режим, один из них открывает отдельную независимую транзакцию;- конкуренция за строку решается версией сущности либо блокировкой при чтении.
Полезно добавить правило, по которому живёте: транзакция короткая, внутри неё нет походов по сети и ожидания пользователя.
Где спотыкаются
Вызывают аннотированный метод из соседнего метода того же класса. Вызов идёт мимо прокси, транзакции нет вовсе, и выясняется это на проде, когда часть записей сохранилась, а часть нет.
Ловят исключение внутри транзакционного метода и не пробрасывают его дальше. Отката не происходит, данные остаются наполовину записанными, а в логе есть только аккуратная строка о том, что ошибка обработана.
Растягивают транзакцию на весь запрос вместе с вызовом внешнего сервиса. Блокировки живут, пока сосед отвечает, пул соединений быстро кончается, и встаёт всё приложение, а не одна операция.