Решение: какой уровень изоляции?
Уровень изоляции транзакций определяет баланс между параллелизмом и согласованностью. Более высокая изоляция означает меньше аномалий, но больше блокировок/конфликтов и повторов. Это дерево помогает выбрать между Read Committed, Repeatable Read/Snapshot и Serializable в зависимости от того, какие аномалии чтения (грязное, неповторяемое, фантомное) вы можете допустить.
Допустимо ли грязное чтение (dirty read)?
Начните с самой базовой аномалии: должна ли транзакция видеть данные, которые ещё не зафиксированы (и могут быть откачены)? Почти ни одному серьёзному приложению это не нужно; в большинстве современных СУБД уровень по умолчанию уже предотвращает грязное чтение. Его ослабляют только ради приблизительных/аналитических грубых подсчётов и максимальной скорости.
- Нет, читать нужно только зафиксированные данные
- Да, достаточно грубого/приблизительного чтения (редко)
Нужно ли получать тот же результат при повторном чтении в той же транзакции?
Исключив грязное чтение, следующий вопрос: если вы дважды читаете одну строку в транзакции, проблема ли для вас увидеть другое значение, потому что кто-то зафиксировал изменение между чтениями (неповторяемое чтение), или появление новых строк (фантом)? Логике, требующей согласованности отчётов/расчётов, обычно нужен согласованный снимок.
- Нет, допустимо, чтобы каждый оператор видел последние зафиксированные данные
- Да, нужен согласованный снимок на всю транзакцию
Должны ли параллельные транзакции быть логически полностью упорядочены?
Вам нужно согласованное чтение; этого достаточно, или параллельные транзакции должны давать результат, как если бы выполнялись по одной, последовательно (serializable)? Если вы допускаете тонкие аномалии, такие как write skew (например, две транзакции читают разные строки и пишут так, что делают недействительными друг друга), достаточно Snapshot; иначе требуется полная сериализация.
- Нет, согласованного снимка достаточно
- Да, никакие аномалии параллелизма недопустимы
Рекомендация: Read Uncommitted (только особые случаи)
Самая низкая изоляция; допускает грязное чтение. Чтение почти не ждёт блокировок, но вы можете увидеть данные, которые будут откачены. Не рекомендуется для приложений общего назначения.
Рекомендация: Read Committed (OLTP по умолчанию)
Каждый оператор видит последние данные, зафиксированные на этот момент; грязное чтение предотвращается. Это уровень по умолчанию в большинстве СУБД, обеспечивающий лучший баланс параллелизма/согласованности для типичных OLTP-нагрузок.
Рекомендация: Repeatable Read / Snapshot (согласованное чтение)
Транзакция работает с согласованным снимком, зафиксированным в её начале (или при первом чтении); данные при чтении не меняются в течение транзакции. Благодаря MVCC читающие не блокируют пишущих, а пишущие — читающих.
Рекомендация: Serializable (полная изоляция)
Самая высокая изоляция: параллельные транзакции дают результат, как если бы выполнялись последовательно (по одной). Предотвращает все аномалии чтения и write skew; цена — больше конфликтов и необходимость повторов.