Основные сведения об уровнях изоляции на основе управления версиями строк
Управление версиями строк — это стандартная структура в SQL Server, используемая для поддержания следующих функций:
создания таблиц inserted и deleted в триггерах. Предусмотрено управление версиями для всех строк, изменяемых триггером, в том числе строк, измененных инструкцией, которая инициировала триггер, а также всех изменений данных, выполненных триггером;
поддержка режима MARS. Если в ходе сеанса MARS выдается инструкция изменения данных (например INSERT, UPDATE или DELETE) в момент, когда есть активный результирующий набор, выполняется управление версиями строк, которых коснулось изменение;
поддержки операций с индексами, в которых задан параметр ONLINE;
поддержки уровней изоляции транзакций на основе управления версиями;
новой реализации уровня изоляции READ COMMITTED, который использует управление версиями строк для обеспечения совместимости считывания на уровне инструкций;
нового уровня изоляции и моментального снимка для обеспечения совместимости считывания на уровне транзакций.
В базе данных tempdb должно быть достаточно места для хранения версий. Если база данных tempdb заполнена, операции обновления прекращают формирование версий и продолжаются до успешного выполнения, а операции считывания завершаются ошибкой, поскольку конкретной требуемой версии строки уже не существует. Это касается работы триггеров, режима MARS и оперативного индексирования. Дополнительные сведения см. в разделе Использование ресурсов при управлении версиями строк.
Использование управления версиями для транзакций READ COMMITTED и моментальных снимков — это процесс, состоящий из двух шагов.
Присвоение любому или обоим параметрам базы данных READ_COMMITTED_SNAPSHOT и ALLOW_SNAPSHOT_ISOLATION значения ON.
Задание соответствующего уровня изоляции транзакций в приложении:
если параметр базы данных READ_COMMITTED_SNAPSHOT имеет значение ON, транзакции, устанавливающие уровень изоляции READ COMMITTED, используют управление версиями строк;
если параметр базы данных ALLOW_SNAPSHOT_ISOLATION имеет значение ON, транзакции могут устанавливать уровень изоляции моментальных снимков.
Если один из параметров базы данных READ_COMMITTED_SNAPSHOT и ALLOW_SNAPSHOT_ISOLATION имеет значение ON, компонент SQL Server Database Engine присваивает порядковый номер транзакции (XSN) каждой транзакции, обрабатывающей данные с помощью управления версиями строк. Транзакции начинаются после выполнения инструкции BEGIN TRANSACTION. Тем не менее порядковый номер транзакции начинается с первой операции считывания или записи после инструкции BEGIN TRANSACTION. Порядковый номер транзакции увеличивается с шагом на единицу.
Если один из параметров базы данных READ_COMMITTED_SNAPSHOT и ALLOW_SNAPSHOT_ISOLATION имеет значение ON, логические копии (версии) сохраняются для всех изменений данных, выполненных в базе данных. При каждом изменении строки конкретной транзакцией экземпляр компонента Database Engine сохраняет версию ранее зафиксированного образа строки в tempdb. Каждой версии присваивается порядковый номер транзакции, выполнившей изменение. Версии измененных строк сцепляются с помощью списка ссылок. Самое последнее значение строки всегда хранится в текущей базе данных с указанием на цепочку версий, хранящихся в базе данных tempdb.
Примечание |
---|
Для модификации типов данных LOB только измененный фрагмент копируется в блок хранения версий базы данных tempdb. |
Версии строк хранятся в соответствии с требованиями транзакций, выполняющихся на уровнях изоляции на основе управления версиями. Компонент Database Engine отслеживает наименьший применимый порядковый номер транзакции и периодически удаляет все версии строк, помеченных порядковыми номерами меньше, чем наименьший применимый порядковый номер транзакции.
Если оба параметра базы данных имеют значение OFF, выполняется управление версиями только строк, измененных триггерами или сеансами MARS либо считанных операциями над индексом ONLINE. Если эти версии строк больше не нужны, они удаляются. Периодически выполняется фоновый поток удаления устаревших версий строк.
Примечание |
---|
Для краткосрочных транзакций версия измененной строки может помещаться в буферный пул без записи в дисковые файлы базы данных tempdb. Если версии строки требуются в течение небольшого промежутка времени, они просто удаляются из буферный пул, тем самым не нагружая дополнительно подсистему ввода-вывода. |
Режим считывания данных
Если транзакции выполняются над считываемыми данными уровня изоляции на основе управления версиями, операции считывания не запрашивают общие блокировки считываемых данных и, как следствие, не блокируют транзакции, изменяющие данные. Кроме того, затраты на блокировку ресурсов сокращаются до минимума, поскольку уменьшается число запрашиваемых блокировок. Изоляция READ COMMITTED, использующая управление версиями строк, и изоляция моментальных снимков служит для обеспечения совместимости операций считывания данных, управляемых по версии, на уровне инструкций и транзакций.
Для всех запросов, включая транзакции, выполняемые с уровнем изоляции на основе управления версиями строк, требуется Sch-S (стабильность схемы) во время компиляции и выполнения блокировок. Поэтому запросы блокируются, если параллельная транзакция удерживает в таблице блокировку Sch-M (изменение схемы). Например, операция языка DDL получает блокировку Sch-M до того, как она изменяет данные схемы. Транзакции с запросами, включая те, которые выполняются с уровнем изоляции на основе управления версиями строк, блокируются при попытке получить блокировку Sch-S. И наоборот, запрос, удерживающий блокировку Sch-S, блокирует параллельную транзакцию, которая пытается получить блокировку Sch-M. Дополнительные сведения о работе блокировок см. в разделе Совместимость блокировок (компонент Database Engine).
Когда запускается транзакция, использующая уровень изоляции моментального снимка, экземпляр компонента Database Engine регистрирует все активные в данный момент транзакции. Когда транзакция моментальных снимков считывает строку, имеющую цепочку версий, компонент Database Engine следует по цепочке и получает строку, если порядковый номер транзакции:
равен ближайшему порядковому номеру, который меньше номера транзакции моментальных снимков, считывающей строку;
не находится в списке транзакций, активных в момент начала транзакции моментальных снимков.
Операции считывания, выполняемые транзакцией моментальных снимков, получают последнюю версию каждой строки, зафиксированной в момент начала транзакции. Тем самым предоставляется согласованный на уровне транзакций моментальный снимок данных на момент начала транзакции.
Транзакции READ COMMITTED, использующие управление версиями строк, выполняются практически также. Разница заключается в том, что транзакция READ COMMITTED не использует собственный порядковый номер транзакции при выборе версий строки. При каждом запуске инструкции транзакции READ COMMITTED считывает последний порядковый номер транзакции, выданный этому экземпляру компонента Database Engine. Этот номер используется для выбора правильных версий строки в данной инструкции. Такой метод дает возможность транзакциям READ COMMITTED видеть моментальный снимок данных на момент начала каждой инструкции.
Примечание |
---|
Даже если транзакция с зафиксированным чтением с помощью управления версиями строк обеспечивает транзакционно согласованное представление данных на уровне инструкций, версии строк, которые она создает или к которым получает доступ, сохраняются до ее завершения. |
Режим изменения данных
В транзакции READ COMMITTED, использующей управление версиями строк, выбор строк для обновления выполняется с помощью просматривания блокировок в случае блокировки обновлений для строки данных по мере считывания значений данных. Это аналогично транзакции READ COMMITTED без использования управления версиями строк. Если строка данных не удовлетворяет условию обновления, блокировка обновления по этой строке отменяется, и блокируется и просматривается следующая строка.
Транзакции, которые выполнялись в рамках изоляции моментальных снимков, применяют оптимистичный подход к изменению данных, запрашивая блокировки данных перед выполнением изменений только, чтобы применить ограничения. В противном случае блокировка данных не запрашивается, пока не потребуется изменить данные. Если строка данных удовлетворяет условию обновления, транзакция моментального снимка удостоверяется, что строка данных не изменялась параллельной транзакцией, зафиксированной после начала транзакции моментального снимка. Если строка данных изменялась вне транзакции моментального снимка, возникает конфликт обновления, и выполнение транзакции моментального снимка прерывается. Конфликт обновления обрабатывается компонентом Database Engine. Отключение функции обнаружения конфликтов обновления невозможно.
Примечание |
---|
Операции обновления, выполняющиеся в рамках изоляции моментальных снимков, внутренне запускаются в рамках изоляции READ COMMITTED, если транзакция моментального снимка обращается к какому-либо из следующих объектов: к таблице с ограничением внешнего ключа; к таблице, на которую ссылается ограничение внешнего ключа другой таблицы; индексированному представлению, ссылающемуся на несколько таблиц. Тем не менее даже в этом случае операция обновления будет удостоверяться, что данные не изменялись другой транзакцией. Если данные изменялись другой транзакцией, транзакция моментального снимка обнаруживает конфликт обновления и прерывается. |
Сводка по режимам работы
В приведенной ниже таблице перечисляются различия между изоляцией моментальных снимков и изоляцией READ COMMITTED при использовании управления версиями строк.
Свойство |
Уровень изоляции зафиксированного чтения, использующий управление версиями строк |
Уровень изоляции моментальных снимков |
---|---|---|
Параметр базы данных, который должен иметь значение ON, чтобы обеспечить требуемую поддержку. |
READ_COMMITTED_SNAPSHOT |
ALLOW_SNAPSHOT_ISOLATION |
Способ запроса в сеансе конкретного типа управления версиями строк. |
Используйте уровень изоляции READ COMMITTED по умолчанию или выполните инструкцию SET TRANSACTION ISOLATION LEVEL для задания уровня изоляции READ COMMITTED. Это можно делать после запуска транзакции. |
Требует выполнения инструкции SET TRANSACTION ISOLATION LEVEL для задания уровня изоляции SNAPSHOT до запуска транзакции. |
Версия данных, считанных инструкциями. |
Все данные, зафиксированные до начала каждой инструкции. |
Все данные, зафиксированные до начала каждой транзакции. |
Способ обработки обновлений. |
Восстановление из версии строки к фактическим строкам для выбора обновляемых данных и использование блокировок обновления по выбранным строкам данных. Запрос монопольных блокировок по строкам изменяемых фактических данных без обнаружения конфликтов обновления. |
Использование версий строки для выбора обновляемых строк. Попытка запроса монопольной блокировки изменяемой строки фактических данных; если данные изменялись другой транзакцией, возникает конфликт обновления и выполнение транзакции моментального снимка прерывается. |
Обнаружение конфликтов обновления. |
Нет. |
Встроенная поддержка. Ее нельзя отключить. |
См. также