Реферат: Версионность в Yukon
Дело в том, что если существует транзакция, зафиксированная после начала работы snapshot-транзакции, и изменения этой транзакции попадают в условия выборки, сделанной snapshot-транзакцией, то вполне могут существовать записи, которые были изменены этой транзакцией после того, как snapshot-запрос их просмотрел, таким образом, что они стали удовлетворять условию snapshot-выборки. То есть получается, что snapshot-транзакция может увидеть только часть изменений, сделанных другой транзакцией, а этого допустить нельзя.
В данном случае поведение Yukon очень похоже на версионное. Но на самом деле он все равно ведет себя немного «по-блокировочному». Проявляется это, например, все в той же ситуации с отсутствием индексов.
Если еще раз выполнить блокирующую транзакцию, не фиксируя ее:
BEGIN TRAN UPDATE tst SET y=3 WHERE x=3 |
А потом попробовать изменить другую запись из snapshot транзакции:
SET TRANSACTION ISOLATION LEVEL SNAPSHOT BEGIN TRAN UPDATE tst SET y=-1 WHERE x=4 COMMIT TRAN |
То snapshot транзакция все равно окажется заблокированной.
Тип | Описание | Объект | Режим | Статус | spid |
RID | 1:1357:2 | 72057594057326592 | U | WAIT | 51 |
Таблица 4
И, что характерно, блокировка произойдет на той же самой записи. Иными словами, в отсутствии индексов Yukon осуществляет поиск по таблице как самый обычный блокировочник, даже при уровне изоляции snapshot. Версионник в данной ситуации сначала сканирует всю таблицу обычным версионным запросом, выясняя нужные записи, а потом обращается с обновлением только к тем, которые подходят под условие выборки, поэтому подобного там не происходит. Yukon же сканирует таблицу, накладывая блокировку обновления на каждую запись, и снимая ее, если запись не удовлетворяет условию выборки, или конвертируя в эксклюзивную, если удовлетворяет. Таким образом, даже если заблокированная запись не удовлетворяет условию выборки обновляющего оператора snapshot-транзакции, в случае отсутствия индексов транзакция все равно застрянет на блокировке.
Результат подобного ожидания snapshot-транзакции вполне закономерен. Если блокирующую транзакцию зафиксировать, то snapshot-транзакция будет отменена, несмотря на то, что формально измененная запись ни до, ни после запроса под условия выборки не попадала. Оборачивается это тем, что если в момент изменения записей в таблице без индексов из snapshot-транзакции будет изменена любая запись, то snapshot-транзакция не выполнится.
Судя по всему, сделать согласованное неблокирующее сканирование при обновлении записей – задача нетривиальная. Поэтому все сделано единообразно, «по-блокировочному». С одной стороны, подобное блокировочное сканирование обещает довольно мрачные перспективы попыткам записи из snapshot-транзакций в неиндексированные таблицы. Но, с другой стороны, это предотвращает некоторые экзотические случаи фантомов, которые пропускает классический snapshot.
Serializable
Несмотря на то, что версионный snapshot помогает избавиться от большинства побочных эффектов, связанных с параллельным выполнением транзакций, вероятность появления некоторых феноменов по-прежнему остается. Чтобы избавиться от подобных эффектов, при работе с классическим версионником и некоторыми гибридами приходится предпринимать дополнительные меры в виде фиктивных изменений или специальных блокировок некоторых записей.
Но Yukon, как и предыдущие версии SQL Server от Microsoft, поддерживает уровень изоляции serializable, который по определению не допускает никаких феноменов. По механизму этот уровень изоляции является чисто блокировочным и никакие версионные запросы, даже на чтение, здесь не поддерживаются, если конечно, не давать специальных указаний оптимизатору.
Заключение
Новая функциональность, безусловно, окажется очень полезной. Самый заметный эффект – это отсутствие блокировок между читающими и пишущими запросами. То есть читающие запросы не блокируют пишущие, и наоборот. Собственно, вся версионность ради этого и затевалась.
У чистых блокировочников, каковым до недавнего времени являлся и Microsoft SQL Server, при наступлении того печального момента, когда читающие запросы начинают довольно сильно конфликтовать с пишущими, используется стандартный архитектурный прием. Механизм работы с данными делится на две сост