En este artículo se describe un problema que se produce durante una consulta de un índice de almacén de columnas agrupadas en Microsoft SQL Server 2014. En este artículo se proporciona una solución a este problema.
Resumen
Al usar una consulta que examina un índice de almacén de columnas agrupadas en Microsoft SQL Server 2014, es posible que, en raras ocasiones, reciba resultados de consulta parciales.
Este problema se produce cuando se ejecuta la siguiente operación.
Paso 1
Una instrucción Transact-SQLTransact-SQL [INSERT o BULK-INSERT] inserta datos en una tabla que tiene índice de almacén de columnas agrupado. Durante esta operación, se aplican las siguientes condiciones:
- Cuando la instrucción Transact-SQLTransact-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 se cierra el grupo de filas R1, no es necesario cerrar el diccionario local D1. Si el diccionario D1 sigue teniendo espacio disponible, puedes dejarlo abierto y volver a usarlo para el nuevo grupo de filas R2.
Paso 2
Si la instrucción Transact-SQLTransact-SQL finaliza de forma anómala o se cancela antes de cerrar el nuevo grupo de filas R2, se aplicarán las siguientes condiciones:
- Los cambios de metadatos del almacén de columnas se producen en subtransacciones que se confirman de forma independiente de la transacción externa.
- En este punto, el grupo de filas R1 continúa en la tabla del sistema en un estado "en construcción" o INVISIBLE, y el segmento S1 hace referencia al diccionario D1.
- No hay ninguna fila creada en la tabla de sistema para el diccionario D1. Esto se debe a que la instrucción Transact-SQLTransact-SQL nunca tiene la oportunidad de cerrar la fila existente. Por lo tanto, la fila existente continúa.
Paso 3
En una situación típica, si la tarea de fondo de la tupla mover se inicia después de que finalice la instrucción Transact-SQLTransact-SQL, la tarea en segundo plano quita el grupo de filas invisible R1 y el segmento S1. Si una nueva instrucción Transact-SQLtransact-SQL se inicia ahora y crea el grupo de filas R3 que tiene un nuevo segmento S3 que requiere un nuevo diccionario local, no puede volver a usar el id. 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 de memoria del diccionario D1 antes de que la tarea mover tupla surta efecto (y se ejecute 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 siguientes motivos:
- SQL Server experimenta sobrecarga de memoria y el contenido en memoria del diccionario D1 se desaloja de la memoria.
- Se reinicia la instancia de SQL Server.
- La base de datos que contiene el índice de almacén de columnas agrupadas se desconecta y vuelve a estar en línea.
Después de que cualquiera de estos eventos ocurra y SQL Server vuelva a cargar las estructuras en memoria, no hay ningún registro que haya existido un diccionario D1 y su id. interno. Esto se debe a que el diccionario D1 no se retiene en las tablas del sistema cuando la instrucción Transact-SQLTransact-SQL ha finalizado o se ha suspendido.
Si la tarea de fondo del mover tupla se inicia en este momento, no se producirá 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 de fondo del mover tupla (según el elemento de viñeta anterior), SQL Server asigna el mismo id. interno al nuevo diccionario D1 y hace referencia al diccionario D1 para el segmento S3 del grupo de filas R3.
Cuando la tarea de fondo del mover 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 mover tupla considera que el nuevo diccionario D1 y el diccionario original D1 que las referencias S1 son las mismas.
Nota Cuando se produce esta condición, no se puede consultar el contenido del grupo de filas R3.
Resolución
El problema se corrigió por primera vez en las siguientes actualizaciones acumulativas para SQL Server:
Actualización acumulativa 1 para SQL Server 2014 SP1
Actualización acumulativa 8 de SQL Server 2014
La corrección para este problema también se incluye en las siguientes actualizaciones generales de la versión de distribución (GDR):
Actualización de seguridad para el SQL Server 2014 QFE
Esta actualización incluye la actualización acumulativa 8, esta corrección importante y las actualizaciones de seguridad MS15-058 necesarias.
Actualización de seguridad para el GDR de SQL Server 2014
Esta actualización incluye esta corrección importante 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 solo incluye esta corrección importante.
Acerca de las actualizaciones acumulativas para SQL Server
Cada nueva actualización acumulativa de SQL Server contiene todas las revisiones y todas las correcciones de seguridad que se incluyeron con la actualización acumulativa anterior. Consulta las últimas actualizaciones acumulativas de SQL Server:
- Actualización acumulativa más reciente para SQL Server 2014 SP1
- Actualización acumulativa más reciente de 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
Msg 5289, Nivel 16, Estado 1, Línea 1
El índice de almacén de columnas agrupadas '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 examina las tablas afectadas después de aplicar esta corrección, recibe el siguiente mensaje de error:
Nota
Msg 5288, Nivel 16, Estado 1, Línea 1
El índice de almacén de columnas tiene uno o varios 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 corregidos exportando en masa los datos de columnas o grupos de filas no afectados y volviendo a cargar los datos después de colocar o crear el índice de almacén de columnas agrupadas. Debe habilitar la marca de seguimiento 10207 para suprimir el error 5288 y volver al comportamiento anterior de omitir 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 utiliza para extraer los segmentos del grupo de filas R3 que no se ven afectados por el diccionario que falta D1.
Consulta de bases de datos afectadasPara determinar si la base de datos que contiene índices de almacén de columnas ya se ve afectada por este problema, ejecute la consulta siguiente:
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 todas las bases de datos que contienen í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: compilación de índice, reorganización de índices, inserción masiva y almacenamiento delta de la tupla.
Antes de ejecutar la consulta, puede deshabilitar la tarea de mover tupla en segundo plano con la marca de seguimiento 634. Utilice 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 comandos BULK INSERT/BCP/SELECT-INTO que inserten 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".