Comments 12
неплохо бы добавить, что snapshot isolation level нет в стандарте sql.
вроде бы нигде, кроме как в ms sql, его не найти.
у оракла формально нет отдельного snapshot isolation level, но он именно так (оптимистично) ведёт себя по-умолчанию.
Изначально (вторая половина 90-х) уровень изоляции Snapshot в БД для x86 был в Interbase — ну, и в Firebird, как в его потомке, потом остался. И, вообще-то, Snapshot, если смотреть с точки зрения уровней изоляции стандарта SQL-92 — это реализация Repeatable Read.
В MS SQL механизм версионирования записей, необходимый для создания снимков (AFAIK версионирование в MS SQL прикрутили «сбоку», за счет создания версий записей в tempdb), появился довольно поздно, до этого (SQL 2000 и ранее) уровень изоляции Repeatable Read реализовывался за счет блокировок записей. И для тех, кто работал в те времена на Delphi, вроде меня, разница была очень заметна: если сделать типовую клиент-серверную программу без изысков (а идеологически в Delphi архитектура такой программы, хоть она и использовала СУБД на сервере, была сделана под работу с настольной БД — dBase, Paradox, и программа могла долго-долго держать откытой «текущую» запись) для работы с базой под Interbase, то в ней было очень сложно наткнуться на блокировку, а вот под MS SQL наткнуться было запросто, а потому программу нужно было делать по-другому.
Ну, и в PostgreSQL, тоже уже давно есть поддержка версионировния записей, Snapshot Isolation тоже реализован. Но появилась эта поддержка все-таки позже, чем в Interbase.
PS Про Oracle — элементарно не в курсе.
Откатываются только WAL логи конкретной страницы, которая нужна SI транзакции, до той точки, когда транзакциия началась. Почитайте AERIS публикацию C. Mohan-a, там все очень хорошо расписано.
И что тогда должна увидеть третья транзакция (допустим, с уровнем изоляции Read Committed ), запущенная после уже завершенной второй, но до завершения первой (которой нужен снимок)? Наверняка ведь она должна увидеть результат второй транзакции. То есть, движок СУБД должен хранить несколько версий одной страницы в своем кэше (но не на диске, раз структура БД этого не позволяе), правильно? То есть, в кэше появляется запись, не имеющая аналога в структуре БД на диске. А куда тогда движок ее запишет, если потребуется эту часть кэша освободить? Нужно какое-то общесистемное хранилище под это дело. То есть, это — не только WAL. В Interbase, к примеру, такого хранилища не было. И потом возникают вопросы — размер этого хранилища, синхронизация доступа к нему (Interbase был родом из Unix и создавал по отдельному рабочему процессу на соединение через fork, так что с синхронизацией ему было непросто)? И — решение вопроса, чтобы это хранилище не стало узким местом во всей СУБД.
Короче, схему создания снимков реализовать-то можно и без изменения структуры БД на диске — но требуется очень серьезная доработка движка.
PS IMHO когда в комментарии его автор ссылается на что-то не общеизвестное, то хорошим тоном является дать гиперссылку.
Исторически Serializable в PostgreSQL был именно Snapshot Isolation (SI). И Repeatable Read (RR) тоже (они не отличались). Но во времена 8.x добавили настоящий Serializable через расширение SI - SSI (Serializable Snapshot Isolation).
Теперь в PostgreSQL SI остался только в RR.
Что любопытно, RR и SI не эквивалентны друг другу, но ни один не слабее другого. Каждый из них допускает разные "аномалии".
А кто реально видел что бы кто-то использовал эти настройки на живой базе в продакшене ? Я вот не видел :/ А хотелось бы...
Serializable vs. Snapshot Isolation Level