Как стать автором
Обновить

Уровни изолированности транзакций для самых маленьких

Уровень сложностиПростой
Время на прочтение11 мин
Количество просмотров21K
Всего голосов 13: ↑10 и ↓3+10
Комментарии9

Комментарии 9

хорошая статья :-)

первый раз понял весь смысл :-)

до этого читал других и не всё понимал

Несколько лет назад в PostgreSQL переделали реализацию для Serializable, в результате чего он стал сравним по скорости с предыдущим уровнем, с одним нюансом: если обнаружен конфликт то транзакция вернёт ошибку и её нужно будет повторить ручками (на уровне приложения). Повтор транзакции по этой ошибке обычно несложно автоматизировать универсальной обёрткой над функцией выполняющей транзакцию.

В результате такого подхода смысл использовать уровни ниже Serializable с PostgreSQL практически пропал (т.е. его вполне разумно включать по умолчанию при условии использования вышеупомянутой обёртки). Этот подход позволяет сэкономить немало сил и времени на анализ допустимости использования менее надёжных уровней изоляции транзакций и отладку связанных с этим очень неприятных багов.

Понижать уровень изоляции при этом подходе может иметь смысл только в виде исключения для отдельных запросов, которые реально уже создали проблемы с производительностью, и при этом для них приемлемы меньшие гарантии изоляции - но в большинстве проектов подходящих под эти условия запросов не найдётся и все запросы будут отлично работать на Serializable.

Оракл - не поддерживает блокировки, поэтому не умеет делать честную сериализуемость.

insert into t(v) select count(*) from t

С точки зрения концепции сериализуемости, запрос выше, запущенный параллельно во множестве транзакций, должен дать возрастающую последовательность чисел в таблице. Оракл так не умеет, у него будут повторения пропуски или ошибки. Хотя формально Оракл соответствует стандарту и не допускает фантомного чтения. MS SQL, Postgres, MySQL прекрасно справляются с таким запросом и выдают ожидаемый результат.

Зачем использовали хибернейт в примерах, чтобы обходить его кэши?

Там же есть пример, позволяющий воспроизвести эту проблему. Но мне в тестах на Kotlin повторить ее не удалось.

Наличие тех или других конкретных феноменов зависит от механизма реализации СУБД.

Если интересна тема транзакций и изоляций, то советую ознакомиться с лекцией. В ней есть упоминание трактата на тысячу страниц по транзакциям :-) Это если захочется глубоко копнуть

Про Cassandra и “консистентность в конечном счете”: вы тут всё в одну кучу смешали. C в ACID и C в CAP - это разные C.

C в ACID - это про то, что данные в не будут нарушать ограничений целостности, наложенных на них правилами базы данных. Например, "Unique Constraints", "Not-Null Constraints" и т.д.

C в CAP - это про то, что данные будут согласованы между репликами.

С в CAP это A в ACID

В картинке "В каких распространённых СУБД используется" не хватает пояснений, что под этим использованием подразумевается.

В частности, в PostgreSQL "Read Uncomitted" и "Repeatable Read", обозначенные вами минусом, вполне себе реализованы и могут быть использованы. Стандарт SQL не требует, чтобы аномалии, характерные для какого-то из уровней изоляции, обязательно присутствовали; он требует отсутствия характерных аномалий. Другими словами, отсутствие того же самого Dirty Read на Read Uncomitted в PostgreSQL допустимо стандартом SQL: стандарт не обязывает, чтобы Dirty Read был реализован в Read Uncomitted; он обязывает, чтобы Dirty Read отсутствовал в Read Comitted.

Так что я бы на вашем месте добавил пояснение по тому, что означают плюсики и минусики, а то может сложиться впечатление, что речь идёт о том, что эти уровни в PostgreSQL не реализованы или реализованы неправильно, а это не так.

Зарегистрируйтесь на Хабре, чтобы оставить комментарий