Какие аномалии бывают при параллельных транзакциях и от чего защищает каждый уровень изоляции?
- Что такое lost update и write skew?
- Чем Repeatable Read отличается от Serializable?
- Какой уровень изоляции по умолчанию в PostgreSQL и MySQL?
Уровни изоляции — компромисс между параллельностью и корректностью: чем ниже уровень, тем больше аномалий пропускается.
- Грязное чтение, неповторяемое чтение, фантомы — аномалии из стандарта SQL
- Потерянное обновление и асимметрия записи (write skew) — важные на практике и не из стандарта
- По умолчанию: PostgreSQL — Read Committed, MySQL InnoDB — Repeatable Read
А ещё Serializable — как будто транзакции шли по очереди; цена — откаты, которые приложение должно повторять
Подробно
Аномалии:
- грязное чтение — видим неподтверждённые изменения другой транзакции, которая потом откатится;
- неповторяемое чтение — прочитали строку дважды и получили разные значения: между чтениями кто-то закоммитил изменение;
- фантом — повторный запрос с условием вернул другой набор строк: кто-то вставил подходящую строку;
- потерянное обновление — обе транзакции прочитали баланс 100, обе записали своё «прочитанное плюс 10», итог 110 вместо 120;
- асимметрия записи (write skew) — обе транзакции проверили условие по общим данным и изменили разные строки, а вместе нарушили инвариант. Классика: «в смене должен остаться хотя бы один дежурный врач» — двое одновременно видят, что дежурят двое, и оба снимаются.
Уровни и что запрещают:
| Уровень | Грязное | Неповторяемое | Фантом | Потерянное обновление | Write skew |
|---|---|---|---|---|---|
| Read Uncommitted | возможно* | возможно | возможно | возможно | возможно |
| Read Committed | нет | возможно | возможно | возможно | возможно |
| Repeatable Read / Snapshot | нет | нет | нет в PostgreSQL** | нет в PostgreSQL*** | возможно |
| Serializable | нет | нет | нет | нет | нет |
* в PostgreSQL Read Uncommitted работает как Read Committed. ** стандарт допускает фантомы на Repeatable Read, но снимок PostgreSQL их не показывает; в InnoDB обычный SELECT тоже читает снимок, а блокирующие чтения используют gap-блокировки. *** PostgreSQL на Repeatable Read откатит вторую транзакцию с ошибкой сериализации; InnoDB — нет, обновление потеряется.
Как защищаться на практике (часто без повышения уровня):
- атомарный
UPDATE ... SET x = x + 10вместо «прочитать — записать»; SELECT ... FOR UPDATE— блокировка строк, которые будем менять;- оптимистическая блокировка по версии;
- от write skew — блокировать строки, по которым проверяется условие (
FOR UPDATEна всех дежурных), материализовать конфликт отдельной строкой или уровень Serializable; - на Serializable и Repeatable Read в PostgreSQL — повторять транзакцию при ошибке
could not serialize access.
Пример
-- write skew на Repeatable Read: обе транзакции успешно закоммитятся
-- T1 -- T2
BEGIN ISOLATION LEVEL REPEATABLE READ; BEGIN ISOLATION LEVEL REPEATABLE READ;
SELECT count(*) FROM doctors SELECT count(*) FROM doctors
WHERE on_call; -- 2 WHERE on_call; -- 2
UPDATE doctors SET on_call = false UPDATE doctors SET on_call = false
WHERE name = 'Анна'; WHERE name = 'Борис';
COMMIT; COMMIT; -- дежурных 0
-- на SERIALIZABLE одна из транзакций получит ошибку сериализацииЧто хотят услышать
- Аномалии стандарта с примерами.
- Потерянное обновление и write skew — уровень middle.
- Таблица уровней и уровни по умолчанию в популярных СУБД.
- Практические способы защиты и повтор транзакций.
Частые ошибки
- Считать, что Repeatable Read защищает от всего, кроме фантомов.
- Повышать уровень изоляции, не добавив повтор при ошибке сериализации.
Проверьте себя
Несколько верных вариантов. Подумайте, потом откройте ответ.
Показать варианты и ответ
- ✓Грязное чтение, неповторяемое чтение и фантомы описаны в стандарте SQL
- ✓Потерянное обновление и write skew важны на практике
- ✗В PostgreSQL по умолчанию Serializable
- ✓Чем ниже уровень изоляции, тем больше аномалий возможно
Что спросят дальше
Связанные вопросы
Разбор собеседования с sotto
После собеседования sotto разбирает разговор: оценка, каждый вопрос — хорошо, частично или слабо, чего не хватило в ответе и над чем поработать к следующему разу. Первые 30 минут бесплатно.