Какие уровни изоляции транзакций существуют и как они помогают избежать проблем с конкурентным доступом?
Что проверяют
Знаете ли вы, какие аномалии бывают при одновременной работе транзакций и какой ценой каждая из них лечится. Вопрос часто идёт следом за @Transactional.
Как отвечать
Сначала назовите аномалии, потом уровни: уровни и определяются через то, что они запрещают.
Аномалии:
- грязное чтение: увидели чужие незакоммиченные данные, а транзакция откатилась;
- неповторяемое чтение: прочитали строку дважды и получили разное, потому что между чтениями её изменили и закоммитили;
- фантомное чтение: повторили запрос по условию и получили новые строки, которых не было.
Уровни (от слабого к строгому):
| Уровень | Грязное | Неповторяемое | Фантомы |
|---|---|---|---|
| Read Uncommitted | возможно | возможно | возможно |
| Read Committed | нет | возможно | возможно |
| Repeatable Read | нет | нет | возможно по стандарту |
| Serializable | нет | нет | нет |
Практика важнее таблицы, и её стоит назвать: в PostgreSQL уровень по умолчанию Read Committed, а Read Uncommitted не существует вовсе (он ведёт себя как Read Committed). В MySQL с InnoDB по умолчанию Repeatable Read, и за счёт блокировок диапазона фантомов там тоже нет.
Плата за строгость: больше блокировок и больше откатов по конфликту сериализации. На Serializable приложение обязано уметь повторить транзакцию, получив ошибку.
Где спотыкаются
Заучивают таблицу из стандарта и не знают, что реальные СУБД ведут себя иначе. Живой пример из PostgreSQL ценится куда выше.
Не могут объяснить разницу между неповторяемым чтением и фантомом: первое про одну строку, второе про набор строк по условию.
Забывают, что уровень изоляции не заменяет бизнес-блокировку: конкурентное списание денег решается SELECT ... FOR UPDATE или проверкой версии, а не повышением уровня.