Este artigo descreve um problema que ocorre durante uma consulta de um índice columnstore clusterizado no Microsoft SQL Server 2014. Este artigo fornece uma resolução para este problema.
Resumo
Quando utiliza uma consulta que analisa um índice columnstore agrupado no Microsoft SQL Server 2014, poderá, em raras condições, receber resultados parciais da consulta.
Esse problema ocorre quando a seguinte operação é executada.
Etapa 1
Uma instrução Transact-SQL [INSERT ou BULK-INSERT] insere dados em uma tabela que tenha o índice columnstore clusterizado. Durante esta operação, aplicam-se as seguintes condições:
- Quando a instrução Transact-SQL atinge o limite do grupo de linhas, ela fecha o grupo de linhas R1 que tem o segmento S1.
- O segmento S1 aponta para o dicionário local D1.
- A instrução continua a inserir linhas no novo grupo de linhas R2.
- Quando o grupo de linhas R1 está fechado, o dicionário local D1 também não precisa ser fechado. Se o dicionário D1 ainda tiver espaço disponível, pode deixá-lo aberto e reutilizá-lo para o novo grupo de linhas R2.
Etapa 2
Se a instrução Transact-SQL for encerrada anormalmente ou cancelada antes de fechar o novo grupo de linhas R2, as seguintes condições se aplicam:
- As alterações de metadados do Columnstore ocorrem em subtransações que são confirmadas independentemente da transação externa.
- Neste ponto, o grupo de linhas R1 persiste na tabela do sistema em um estado "em construção" ou INVISÍVEL, e o segmento S1 referencia o dicionário D1.
- Não é criada nenhuma linha na tabela do sistema para o dicionário D1. Isso ocorre porque a instrução Transact-SQL nunca tem a oportunidade de fechar a linha existente. Portanto, a linha existente persiste.
Etapa 3
Em uma situação típica, se a tarefa em segundo plano do movimentador de cadeia for iniciada depois que a instrução Transact-SQL terminar, a tarefa em segundo plano removerá o grupo de linhas invisível R1 e o segmento S1. Se uma nova instrução Transact-SQL for iniciada agora e criar o grupo de linhas R3 com um novo segmento S3 que requer um novo dicionário local, não será possível reutilizar a ID interna do dicionário D1. Isso ocorre porque o estado na memória do columnstore controla as IDs de dicionário usadas. Portanto, o segmento S3 fará referência ao novo dicionário D2.
Observação A condição nesta etapa é uma condição comum. Portanto, não ocorre nenhum dano.
Etapa 4
Se SQL Server perder o estado na memória do dicionário D1 antes que a tarefa de movimentação de cadeia de caracteres entre em vigor (e seja executada conforme descrito na Etapa 3), ocorrerá o problema descrito neste artigo.
Anotações
Este evento ocorre por qualquer um dos seguintes motivos:
- SQL Server sofre sobrecarga de memória e os conteúdos na memória do dicionário D1 são removidos da memória.
- A instância do SQL Server é reiniciada.
- A base de dados que contém o índice columnstore agrupado fica offline e, em seguida, volta a ficar online.
Depois que qualquer um desses eventos ocorrer e SQL Server recarregar as estruturas na memória, não há registro de que um dicionário D1 e sua ID interna existiram. Isso ocorre porque o dicionário D1 não foi retido nas tabelas do sistema quando a instrução Transact-SQL foi encerrada ou ocultada.
Se a tarefa em segundo plano de movimentação de cadeia começar neste ponto, não ocorrerão erros porque as condições descritas na Etapa 3 se aplicam.
Se um novo grupo de linhas R3 for criado antes do início da tarefa em segundo plano do movimentador de tupla (de acordo com o item de marca anterior), SQL Server atribuirá a mesma ID interna ao novo dicionário D1 e fará referência ao dicionário D1 para o segmento S3 no grupo de linhas R3.
Quando a tarefa em segundo plano do movimentador de tupla começa após a ação anterior, ela remove o grupo de linhas invisível R1 e seus segmentos S1 juntamente com o novo dicionário D1. Isso ocorre porque o tupla mover considera que o novo dicionário D1 e o dicionário original D1 que S1 referencia são os mesmos.
Observação Quando essa condição ocorre, você não pode consultar o conteúdo do grupo de linhas R3.
Resolução
O problema foi corrigido primeiro nas seguintes atualizações cumulativas para SQL Server:
Atualização cumulativa 1 para SQL Server 2014 SP1
Atualização cumulativa 8 para SQL Server 2014
A correção para este problema também está incluída nas seguintes atualizações GDR (General Distribution Release):
Atualização de segurança para o SQL Server 2014 QFE
Esta atualização inclui a Atualização Cumulativa 8, esta correção importante e as atualizações de segurança MS15-058 necessárias.
Atualização de segurança para SQL Server 2014 GDR
Esta atualização inclui esta correção importante e correções de segurança cumulativas até à atualização MS15-058.
Atualização não relacionada à segurança para SQL Server 2014 Service Pack 1 GDR
Esta atualização inclui apenas esta correção importante.
Sobre atualizações cumulativas para o SQL Server
Cada nova atualização cumulativa para SQL Server contém todos os hotfixes e todas as correções de segurança que foram incluídas com a atualização cumulativa anterior. Consulte as atualizações cumulativas mais recentes para SQL Server:
- Atualização cumulativa mais recente para o SQL Server 2014 SP1
- Atualização cumulativa mais recente para o SQL Server 2014
Mais informações
Mensagens de erroEm um banco de dados atualmente afetado, se você executar DBCC CHECKDB depois de aplicar essa correção, você receber a seguinte mensagem de erro:
Observação
Msg 5289, Nível 16, Estado 1, Linha 1
O índice de armazenamento de colunas agrupadas "cci" na tabela "t" tem um ou mais valores de dados que não correspondem aos valores de dados num dicionário. Restaure os dados a partir de uma cópia de segurança.
Numa base de dados atualmente afetada, quando executa uma consulta que analisa as tabelas afetadas depois de aplicar esta correção, recebe a seguinte mensagem de erro:
Observação
Msg 5288, Nível 16, Estado 1, Linha 1
O índice Columnstore tem um ou mais valores de dados que não correspondem aos valores de dados num dicionário. Execute DBCC CHECKDB para obter mais informações.
Se você receber esses erros, poderá salvar os dados não corrompidos exportando em massa os dados de colunas/grupos de linhas não afetados e, em seguida, recarregando os dados depois de descartar ou criar o índice columnstore clusterizado. Deve ativar o sinalizador de rastreio 10207 para suprimir o erro 5288 e reverter ao comportamento antigo de ignorar grupos de linhas danificados.
Observação As mensagens de erro 5288 e 5289 são geradas para este grupo de linhas R3 que tem segmento S3. O sinalizador de rastreamento 10207 é usado para extrair os segmentos do grupo de linhas R3 que não são afetados pelo dicionário D1 ausente.
Consulta para bancos de dados afetadosPara determinar se o banco de dados que contém índices columnstore já é afetado por esse problema, execute a seguinte 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
Anotações
Tem de executar esta consulta em todas as bases de dados que contenham índices columnstore no servidor que está a executar o SQL Server. Um conjunto de resultados vazio indica que a base de dados não é afetada.
Execute esta consulta durante um período em que não existe nenhuma atividade que crie novos grupos de linhas ou altere o estado de grupos de linhas existentes. Por exemplo, as seguintes atividades podem modificar o estado de grupos de linhas: compilação de índice, reorganização de índice, inserção em massa, compactação de tupla compactando repositórios delta.
Antes de executar a consulta, pode desativar a tarefa mover de cadeia de identificação em segundo plano utilizando o sinalizador de rastreio 634. Use este comando para desativar a tarefa em segundo plano: DBCC TRACEON ( 634 , -1 ). Depois de concluir a execução da consulta, lembre-se de reativar a tarefa em segundo plano utilizando o comando: DBCC TRACEOFF ( 634 , -1 ).
Certifique-se também de que não existem comandos BULK INSERT/BCP/SELECT-INTO a inserir dados nas tabelas que utilizam o índice columnstore enquanto esta consulta está em execução.
Recomenda-se que utilize estes passos para impedir que a consulta devolva falsos positivos.
Status
A Microsoft confirmou que este é um problema nos produtos da Microsoft listados na seção "Aplica-se a".