TL; DR: Tengo una corrupción no reparable en una vista indizada. Aquí están los detalles:
Corriendo
DBCC CHECKDB([DbName]) WITH EXTENDED_LOGICAL_CHECKS, DATA_PURITY, NO_INFOMSGS, ALL_ERRORMSGS
en una de mis bases de datos produce el siguiente error:
Mensaje 8907, Nivel 16, Estado 1, Línea 1 El índice espacial, el índice XML o la vista indizada 'ViewName' (ID de objeto 784109934) contiene filas que no fueron producidas por la definición de la vista. Esto no representa necesariamente un problema de integridad con los datos en esta base de datos. (...)
CHECKDB encontró 0 errores de asignación y 1 errores de coherencia en la tabla 'ViewName'.
repair_rebuild es el nivel mínimo de reparación (...).
Entiendo que este mensaje indica que los datos materializados de la vista indexada 'ViewName' no son idénticos a los que produce la consulta subyacente. Sin embargo, la verificación manual de los datos no genera ninguna discrepancia:
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
se usó para forzar el uso del (único) índice en ViewName
. FORCESCAN
se usó para evitar que ocurriera coincidencia de vista indexada. El plan de ejecución confirma que ambas medidas están funcionando.
Aquí no se devuelven filas, lo que significa que las dos tablas son idénticas. (Solo hay columnas enteras y guid, las colaciones no entran en juego).
El error no se puede solucionar recreando el índice en la vista o ejecutando DBCC CHECKDB REPAIR_ALLOW_DATA_LOSS
. Repetir las correcciones tampoco ayudó. ¿Por qué DBCC CHECKDB
informa este error? Cómo deshacerse de él?
(Incluso si la reconstrucción lo solucionaba, mi pregunta seguiría en pie: ¿por qué se informa un error aunque mis consultas de verificación de datos se ejecutan correctamente?)
Actualización: el error se ha solucionado en algunas versiones. Ya no puedo reproducirlo en SQL Server 2014 SP2 CU 5. El SP2 KB 2014 contiene una corrección sin artículo de KB: Creating non-clustered index causes DBCC CheckDB With Extended_Logical_Checks to raise corruption error
. Los dos errores de conexión sobre esto se han cerrado:
- 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]
notación no funciona en el marcado de comentarios.Respuestas:
El procesador de consultas puede generar un plan de ejecución no válido para la consulta (correcta) generada por DBCC para verificar que el índice de vista produce las mismas filas que la consulta de vista subyacente.
El plan producido por el procesador de consultas maneja incorrectamente
NULLs
laImageObjectID
columna. Motiva incorrectamente que la consulta de vista rechazaNULLs
esta columna, cuando no lo hace. Pensando queNULLs
están excluidos, puede hacer coincidir el índice filtrado no agrupado en laUsers
tabla que se filtraImageObjectID IS NOT NULL
.Al producir un plan que utiliza este índice filtrado, asegura que no se encuentren filas con
NULL
inImageObjectID
. Estas filas se devuelven (correctamente) desde el índice de vista, por lo que parece que hay una corrupción cuando no la hay.La definición de la vista es:
La
ON
cláusula de comparación de igualdad entreAdminUserID
yID
rechazaNULLs
en esas columnas, pero no de laImageObjectID
columna.Parte de la consulta generada por DBCC es:
Este es un código genérico que compara valores de manera
NULL
consciente. Ciertamente es detallado, pero la lógica está bien.El error en el razonamiento del procesador de consultas significa que se puede generar un plan de consulta que usa incorrectamente el índice filtrado, como en el fragmento de plan de ejemplo a continuación:
La consulta DBCC toma una ruta de código diferente a través del procesador de consultas de las consultas de los usuarios. Esta ruta de código contiene el error. Cuando se genera un plan que usa el índice filtrado, no se puede usar con la
USE PLAN
sugerencia para forzar esa forma de plan con el mismo texto de consulta enviado desde una conexión de base de datos de usuario.La ruta del código del optimizador principal (para consultas de usuarios) no contiene este error, por lo que es específica para consultas internas como las generadas por DBCC.
fuente
La investigación adicional muestra que este es un error en DBCC CHECKDB. Se ha abierto un error de Microsoft Connect: error de DBCC CHECKDB no reparable (que también es un falso positivo y de otro modo extraño) . Afortunadamente, pude producir una reproducción para que el error pueda ser encontrado y reparado.
El error puede ocultarse jugando con el esquema de la base de datos. Eliminar un índice filtrado no relacionado o eliminar el filtro oculta el error. Para más detalles, consulte el elemento de conexión.
El elemento de conexión también contiene la consulta interna que DBCC CHECKDB usa para validar el contenido de la vista. No devuelve resultados, lo que demuestra que se trata de un error.
El error se ha solucionado en algunas versiones. Ya no puedo reproducirlo en SQL Server 2014 SP2 CU 5.
fuente