TL; DR: у меня есть нефиксированное искажение в индексированном представлении. Вот подробности:
Бег
DBCC CHECKDB([DbName]) WITH EXTENDED_LOGICAL_CHECKS, DATA_PURITY, NO_INFOMSGS, ALL_ERRORMSGS
на одной из моих баз выдает следующую ошибку:
Сообщение 8907, уровень 16, состояние 1, строка 1 Пространственный индекс, индекс XML или индексированное представление ViewName (идентификатор объекта 784109934) содержит строки, которые не были созданы определением представления. Это не обязательно представляет проблему целостности данных в этой базе данных. (...)
CHECKDB обнаружил 0 ошибок размещения и 1 ошибок согласованности в таблице «ViewName».
repair_rebuild - минимальный уровень ремонта (...).
Я понимаю, что это сообщение указывает на то, что материализованные данные индексированного представления ViewName не совпадают с тем, что создает базовый запрос. Однако ручная проверка данных не выявляет никаких расхождений:
SELECT * FROM ViewName WITH (NOEXPAND)
EXCEPT
SELECT ...
from T1 WITH (FORCESCAN)
join T2 on ...
SELECT ...
from T1 WITH (FORCESCAN)
join T2 on ...
EXCEPT
SELECT * FROM ViewName WITH (NOEXPAND)
NOEXPAND
был использован для принудительного использования (только) индекса на ViewName
. FORCESCAN
был использован для предотвращения совпадения индексированного представления. План выполнения подтверждает, что обе меры работают.
Здесь не возвращаются строки, это означает, что две таблицы идентичны. (Есть только целочисленные столбцы и столбцы guid, параметры сортировки не вступают в игру).
Ошибка не может быть исправлена путем воссоздания индекса в представлении или выполнения DBCC CHECKDB REPAIR_ALLOW_DATA_LOSS
. Повторение исправлений также не помогло. Почему DBCC CHECKDB
сообщает об этой ошибке? Как от этого избавиться?
(Даже если восстановление будет исправлено, мой вопрос не изменится - почему выдается сообщение об ошибке, хотя мои запросы на проверку данных выполняются успешно?)
Обновление: ошибка была исправлена в некоторых выпусках. Я больше не может воспроизвести его в SQL Server 2014 с пакетом обновления 2 CU 5. 2014 SP2 KB содержит исправление без KB статьи: Creating non-clustered index causes DBCC CheckDB With Extended_Logical_Checks to raise corruption error
. Две ошибки подключения по этому поводу были закрыты:
- https://connect.microsoft.com/SQLServer/feedback/details/847233/creating-non-clustered-index-causes-dbcc-checkdb-with-extended-logical-checks-to-raise-corruption-error
- https://connect.microsoft.com/SQLServer/feedback/details/795478/unfixable-dbcc-checkdb-error-that-is-also-a-false-positive-and-otherwise-strange
If the indexed view does not contain an aggregate over values of type float or real and you receive errors 8907 or 8708, drop the index on the view and re-create it. Do not use ALTER INDEX REBUILD to try to remove the differences between the stored and the computed view, because ALTER INDEX REBUILD does not recalculate the view before rebuilding the index. Then run DBCC CHECKTABLE on the View to verify no differences remain.
[1]
Нотация не работает в замечании наценке вниз.Ответы:
Обработчик запросов может создать неверный план выполнения для (правильного) запроса, сгенерированного DBCC, чтобы проверить, что индекс представления создает те же строки, что и базовый запрос представления.
План производства процессора запроса неправильно обрабатывает
NULLs
дляImageObjectID
столбца. Это неправильно приводит к тому, что запрос представления отклоняетNULLs
этот столбец, если это не так. Считая, чтоNULLs
это исключено, он может сопоставить отфильтрованный некластеризованный индекс вUsers
таблице, по которой выполняется фильтрацияImageObjectID IS NOT NULL
.Создав план, который использует этот отфильтрованный индекс, он гарантирует, что строки с
NULL
inImageObjectID
не встретятся. Эти строки возвращаются (правильно) из индекса представления, поэтому кажется, что существует искажение, когда его нет.Определение представления:
ON
Сравнение положения равенства междуAdminUserID
иID
отбросамиNULLs
в этих колонках, но не изImageObjectID
колонки.Часть сгенерированного DBCC запроса:
Это универсальный код, который сравнивает значения в
NULL
привычной манере. Это, конечно, многословно, но логика в порядке.Ошибка в рассуждении обработчика запросов означает, что план запроса, который неправильно использует отфильтрованный индекс, может быть создан, как в приведенном ниже фрагменте плана:
Запрос DBCC принимает другой путь кода через обработчик запросов от пользовательских запросов. Этот путь кода содержит ошибку. Когда создается план с использованием отфильтрованного индекса, его нельзя использовать с
USE PLAN
подсказкой для принудительного применения этой формы плана с помощью того же текста запроса, который был отправлен из подключения к пользовательской базе данных.Основной путь кода оптимизатора (для пользовательских запросов) не содержит этой ошибки, поэтому он специфичен для внутренних запросов, например, сгенерированных DBCC.
источник
Дальнейшее расследование показывает, что это ошибка в DBCC CHECKDB. Была открыта ошибка Microsoft Connect: нефиксированная ошибка DBCC CHECKDB (которая также является ложно-положительной и в других отношениях странной) . К счастью, мне удалось создать репродукцию, чтобы ошибка была найдена и исправлена.
Ошибка может быть скрыта, играя со схемой базы данных. Удаление несвязанного отфильтрованного индекса или удаление фильтра скрывает ошибку. Для получения подробной информации, пожалуйста, смотрите пункт подключения.
Элемент подключения также содержит внутренний запрос, который DBCC CHECKDB использует для проверки содержимого представления. Он не возвращает результатов, показывая, что это ошибка.
Ошибка была исправлена в некоторых выпусках. Я больше не могу воспроизвести его в SQL Server 2014 SP2 CU 5.
источник