11.12.25

Как оператор SELECT может изменить базу данных?

Автор: Paul Randal, SQLskills SQL101: How can a SELECT cause a database to change?

Как писала в блоге Кимберли, SQLskills начинает инициативу — ведение блога на базовые темы, которую мы называем SQL101. Мы все будем писать о вещах, которые часто делаются неправильно, о технологиях, используемых неверно, или о случаях, когда существует множество заблуждений, ведущих к серьёзным проблемам.

Это интересное заблуждение, о котором меня спрашивали на прошлой неделе: (перефразируя) «Наверняка операция SELECT не может привести к изменению базы данных, потому что она просто читает данные, а не изменяет их каким-либо образом, верно?».

Что ж, нет. На самом деле существует довольно много побочных эффектов у запросов, которые только читают данные и никогда не выполняют изменения данных (не считая, конечно, SELECT ... INTO). Вот четыре, которые сразу приходят на ум…

Создание статистик

Если для свойства базы данных Auto Create Statistics установлено значение True, то во время компиляции запроса, когда оптимизатор запросов определяет, что можно создать статистику, которая поможет процессу оптимизации, он создаст эту статистику до продолжения оптимизации, тем самым изменяя базу данных. Ваш оператор SELECT может вызвать это.

Обновление статистик

Если для свойства базы данных Auto Update Statistics установлено значение True, то во время компиляции запроса, когда необходимая статистика определяется как устаревшая, она будет автоматически обновлена до продолжения оптимизации, тем самым изменяя базу данных. Ваш оператор SELECT может вызвать это. Кроме того, если включено свойство Auto Update Statistics Asynchronously, статистика будет автоматически обновлена, но уже после процесса оптимизации (чтобы компилирующий запрос не должен был ждать).

Очистка «призрачных» записей

Очистка «фантомных» записей — это своеобразный процесс удаления удалённых записей. Для всех индексов и для куч, когда задействована какая-либо форма изоляции моментальных снимков, удаление записи просто помечает её как удалённую. После фиксации удаляющей транзакции удалённая запись позже удаляется фоновым процессом, называемым задачей очистки «фантомных» записей (ghost cleanup task). Однако интересно то, что удалённая запись не сразу попадает в список дел задачи. Обычно только при следующем использовании страницы файла данных подсистема хранения видит, что есть удалённая запись, и добавляет её в список дел задачи. Таким образом, ваш оператор SELECT может стать тем самым «следующим» использованием страницы файла данных с недавно удалённой записью, что приведёт к очистке этой записи задачей очистки «фантомных» записей.

Хранилище запросов (Query Store)

Начиная с SQL Server 2016, если у вас включено хранилище запросов, по умолчанию каждое выполнение запроса приведёт к захвату некоторых метрик и их сохранению в системных таблицах хранилища запросов (к которым можно обращаться через различные DMV). Вы можете остановить захват информации для всех запросов, установив QUERY_CAPTURE_MODE в значение AUTO, что заставит его не захватывать «незначительные» запросы, но вы не можете указать, что означает «незначительные». В любом случае, ваш оператор SELECT может вызвать это.

Итог

Итак, как видите, даже если вы сознательно не вносите изменения в базу данных, это не значит, что вы не спровоцируете что-то ещё в SQL Server на внесение изменений. И ещё есть опция Auto Shrink для базы данных, которую, конечно же, никогда не следует включать! (см. объяснение здесь…)



Комментариев нет:

Отправить комментарий