En este artículo se describe un problema que se produce durante una consulta de un índice de almacén de columnas agrupado en Microsoft SQL Server 2014. En este artículo se proporciona una solución a este problema.
Resumen
Cuando utiliza una consulta que examina un índice de almacén de columnas agrupado en Microsoft SQL Server 2014, puede, en raras condiciones, recibir resultados parciales de la consulta.
Este problema se produce cuando se ejecuta la siguiente operación.
Paso 1
Una instrucción Transact-SQL [INSERT o BULK-INSERT] inserta datos en una tabla que tiene un índice de almacén de columnas agrupado. Durante esta operación, se aplican las siguientes condiciones:
- Cuando la instrucción Transact-SQL alcanza el umbral del grupo de filas, cierra el grupo de filas R1 que tiene el segmento S1.
- El segmento S1 apunta al diccionario local D1.
- La instrucción continúa insertando filas en el nuevo grupo de filas R2.
- Cuando el grupo de filas R1 está cerrado, no es necesario cerrar también el diccionario local D1. Si el diccionario D1 todavía tiene espacio disponible, puede dejarlo abierto y volver a usarlo para el nuevo grupo de filas R2.
Paso 2
Si la instrucción Transact-SQL finaliza de forma anormal o se cancela antes de cerrar el nuevo grupo de filas R2, se aplican las condiciones siguientes:
- Los cambios en los metadatos del almacén de columnas se producen en subtransacciones que se confirman independientemente de la transacción externa.
- En este punto, el grupo de filas R1 persiste en la tabla del sistema en un estado "en construcción" o INVISIBLE, y el segmento S1 hace referencia al diccionario D1.
- No se ha creado ninguna fila en la tabla del sistema para el diccionario D1. Esto se debe a que la instrucción Transact-SQL nunca tiene la oportunidad de cerrar la fila existente. Por lo tanto, la fila existente persiste.
Paso 3
En una situación típica, si la tarea en segundo plano del motor de la tupla se inicia después de que finalice la instrucción Transact-SQL, la tarea en segundo plano quita el grupo de filas invisible R1 y el segmento S1. Si ahora se inicia una nueva instrucción Transact-SQL y crea el grupo de filas R3 que tiene un nuevo segmento S3 que requiere un nuevo diccionario local, no puede reutilizar el identificador interno del diccionario D1. Esto se debe a que el estado en memoria del almacén de columnas realiza un seguimiento de los identificadores de diccionario que se usan. Por lo tanto, el segmento S3 hará referencia al nuevo diccionario D2.
Nota: La condición de este paso es una condición común. Por lo tanto, no se produce ningún daño.
Paso 4
Si SQL Server pierde el estado en memoria del diccionario D1 antes de que la tarea de mover tupla surta efecto (y funcione como se describe en el Paso 3), se produce el problema que se describe en este artículo.
Notas
Este evento se produce por cualquiera de los motivos siguientes:
- SQL Server experimenta una sobrecarga de memoria y el contenido en memoria del diccionario D1 se expulsa de la memoria.
- Se reiniciará la instancia de SQL Server.
- La base de datos que contiene el índice de almacén de columnas agrupado se desconecta y, después, vuelve a estar en línea.
Después de que se produzca cualquiera de estos eventos y SQL Server vuelva a cargar las estructuras en memoria, no hay registro de que existiera un diccionario D1 y su identificador interno. Esto se debe a que el diccionario D1 no se ha conservado en las tablas del sistema cuando la instrucción Transact-SQL ha finalizado o se ha otorgado.
Si la tarea en segundo plano del motor de tupla se inicia en este momento, no se produce ningún error porque se aplican las condiciones descritas en el paso 3.
Si se crea un nuevo grupo de filas R3 antes de que se inicie la tarea en segundo plano del motor de la tupla (según el elemento de viñeta anterior), SQL Server asigna el mismo identificador interno al nuevo diccionario D1 y hace referencia al diccionario D1 para el segmento S3 del grupo de filas R3.
Cuando la tarea en segundo plano del motor de tupla se inicia después de la acción anterior, quita el grupo de filas invisible R1 y sus segmentos S1 junto con el nuevo diccionario D1. Esto ocurre porque el impulsor de la tupla considera que el nuevo diccionario D1 y el diccionario original D1 al que hace referencia S1 son lo mismo.
Nota: Cuando se produce esta condición, no puede consultar el contenido del grupo de filas R3.
Resolución
Este problema se ha corregido por primera vez en las siguientes actualizaciones acumulativas para SQL Server:
Actualización acumulativa 1 para SQL Server 2014 SP1
Actualización acumulativa 8 para SQL Server 2014
La corrección de este problema también se incluye en las siguientes actualizaciones de la versión de distribución general (GDR):
Actualización de seguridad para SQL Server 2014 QFE
Esta actualización incluye la actualización acumulativa 8, esta importante corrección y las actualizaciones de seguridad necesarias de MS15-058.
Actualización de seguridad para SQL Server 2014 GDR
Esta actualización incluye esta importante corrección y correcciones de seguridad acumulativas a través de MS15-058.
Actualización no relacionada con la seguridad para SQL Server 2014 Service Pack 1 GDR
Esta actualización incluye solo esta corrección importante.
Acerca de las actualizaciones acumulativas para SQL Server
Cada nueva actualización acumulativa para SQL Server contiene todas las revisiones y correcciones de seguridad que se incluyeron con la actualización acumulativa anterior. Consulte las actualizaciones acumulativas más recientes para SQL Server:
- Actualización acumulativa más reciente para SQL Server 2014 SP1
- Actualización acumulativa más reciente para SQL Server 2014
Más información
Mensajes de errorEn una base de datos afectada actualmente, si ejecuta DBCC CHECKDB después de aplicar esta corrección, recibirá el siguiente mensaje de error:
Nota
Msj 5289, Nivel 16, Estado 1, Línea 1
El índice de almacén de columnas agrupado "cci" de la tabla "t" tiene uno o varios valores de datos que no coinciden con los valores de datos de un diccionario. Restaurar los datos a partir de una copia de seguridad.
En una base de datos afectada actualmente, al ejecutar una consulta que examine las tablas afectadas después de aplicar esta corrección, recibirá el siguiente mensaje de error:
Nota
Msj 5288, Nivel 16, Estado 1, Línea 1
El índice de almacén de columnas tiene uno o más valores de datos que no coinciden con los valores de datos de un diccionario. Ejecute DBCC CHECKDB para obtener más información.
Si recibe estos errores, puede guardar los datos no dañados exportando de forma masiva los datos de las columnas o grupos de filas no afectados y, a continuación, volviendo a cargar los datos después de quitar o crear el índice de almacén de columnas agrupado. Debe habilitar la marca de seguimiento 10207 para suprimir el error 5288 y revertir al comportamiento anterior de omitir los grupos de filas dañados.
Nota: Los mensajes de error 5288 y 5289 se generan para este grupo de filas R3 que tiene el segmento S3. La marca de seguimiento 10207 se usa para extraer los segmentos del grupo de filas R3 que no se ven afectados por la falta del diccionario D1.
Consulte las bases de datos afectadasPara determinar si la base de datos que contiene índices de almacén de columnas ya está afectada por este problema, ejecute la siguiente consulta:
select
object_name(i.object_id) as table_name,
i.name as index_name,
p.partition_number,
count(distinct s.segment_id) as damaged_rowgroups
from
sys.indexes i
join sys.partitions p on p.object_id = i.object_id and p.index_id = i.index_id
join sys.column_store_row_groups g on g.object_id = i.object_id and g.index_id = i.index_id and g.partition_number = p.partition_number
join sys.column_store_segments s on s.partition_id = p.partition_id and s.segment_id = g.row_group_id
where
i.type in (5, 6)
and s.secondary_dictionary_id <> -1
and g.state_description = 'COMPRESSED'
and s.secondary_dictionary_id not in
(
select dictionary_id from sys.column_store_dictionaries d
where d.hobt_id = p.hobt_id and d.column_id = s.column_id
)
group by
object_name(i.object_id),
i.name,
p.partition_number
Notas
Tiene que ejecutar esta consulta en cada base de datos que contenga índices de almacén de columnas en el servidor que ejecuta SQL Server. Un conjunto de resultados vacío indica que la base de datos no se ve afectada.
Ejecute esta consulta durante un período en el que no haya actividad que cree nuevos grupos de filas o cambie el estado de los grupos de filas existentes. Por ejemplo, las actividades siguientes pueden modificar el estado de los grupos de filas: generación de índices, reorganización de índices, inserción masiva, movimiento de tupla compresión de almacenes delta.
Antes de ejecutar la consulta, puede deshabilitar la tarea de mover tuplas en segundo plano mediante la marca de seguimiento 634. Use este comando para deshabilitar la tarea en segundo plano: DBCC TRACEON ( 634 , -1 ). Cuando la consulta termine de ejecutarse, recuerde volver a habilitar la tarea en segundo plano mediante el comando: DBCC TRACEOFF ( 634 , -1 ).
Asegúrese también de que no hay ningún comando BULK INSERT/BCP/SELECT-INTO que inserte datos en las tablas que usan el índice de almacén de columnas mientras se ejecuta esta consulta.
Se recomienda seguir estos pasos para evitar que la consulta devuelva falsos positivos.
Estado
Microsoft ha confirmado que se trata de un problema de los productos de Microsoft que se enumeran en la sección "Aplicable a".