O DB do SQL Server se torna inutilizável da noite para o dia

9

Ontem, meu banco de dados do SQL Server estava bom. Hoje é quase inutilizável - diminui a velocidade de um fator entre cinco e vinte, dependendo de quando eu o acertei.

Alguns dados foram adicionados ao servidor em um processo de carregamento noturno, mas nada como um volume que deve impactar tanto um banco de dados. Cerca de 50.000 registros de texto sem formatação (sem XML ou outros sinais de alerta).

O servidor foi corrigido esta manhã antes de reiniciá-lo. No entanto, nenhum de nossos outros servidores de banco de dados que também foram corrigidos está se comportando de maneira diferente.

O Monitor de Recursos parece sugerir que sua E / S de disco está com defeito. Está rodando com quase 100% da capacidade no arquivo .mdf o tempo todo, mesmo quando não há muita coisa acontecendo no banco de dados. O acesso ao Templog.ldf também está executando bastante alto.

Ninguém aqui é um DBA especialista (somos todos desenvolvedores com uma quantidade variável de habilidades em SQL) e estamos todos confusos com o que aconteceu. Tentamos rodar sp_updatestats e mover alguns dos grandes índices para diferentes discos, sem sucesso.

Eu acho que isso deve ter algo a ver com o adesivo - parece uma coincidência demais. Um colega está convencido de que o carregamento de dados fez com que o tamanho do mdf aumentasse até um ponto em que fez com que os planos de execução se tornassem ineficientes.

O que diabos causou isso? Como podemos descobrir e o que podemos fazer para corrigi-lo?

EDITAR:

Usar sp_WhoIsActivenão revela nada fora do comum. Ele registra meu próprio uso do sproc e alguns comandos de um colega que atualmente está tentando mover outro índice. Isso provavelmente está atrasando o banco de dados agora, mas estava funcionando tão mal antes.

É a versão padrão do SQL Server 2008 R2. SELECT @@VERSIONdá:

Microsoft SQL Server 2008 R2 (SP2) - 10.50.4033.0 (X64)
9 de julho de 2014 16:04:25
Direitos autorais (c) Microsoft Corporation Standard Edition (64 bits) no Windows NT 6.1 (Build 7601: Service Pack 1) (Hypervisor )

O servidor possui 72 GB de RAM e três processadores quad-core de 2 GHz.

O patch foi aplicado apenas ao Windows. Não houve outras alterações além do patch.

Configurações selecionadas:

_id     name                        value   minimum     maximum     value_in_use    description                                 is_dynamic  is_advanced
1540    min memory per query (KB)   1024    512         2147483647  1024            minimum memory per query (kBytes)           1           1
1541    query wait (s)              -1      -1          2147483647  -1              maximum time to wait for query memory (s)   1           1
1543    min server memory (MB)      0       0           2147483647  16              Minimum size of server memory (MB)          1           1
1544    max server memory (MB)      65536   16          2147483647  65536           Maximum size of server memory (MB)          1           1

ATUALIZAÇÃO: Mudar índices e tabelas para diferentes partições de disco parece melhorar as coisas. Ainda estou confuso sobre como poderíamos ter atingido um ponto de inflexão tão repentinamente com resultados tão drásticos.

Bob Tway
fonte
Você pode executar sp_whoisactive por 5 minutos e capturar a saída na tabela. Você pode baixá-lo aqui e isso vai mostrar como você pode capturar a saída para a mesa
Kin Shah
Bem, se você reiniciou o servidor, isso significa que todos os seus dados em cache foram despejados do buffer pool e todos os seus planos de execução em cache também foram despejados. Isso significa que o SQL Server precisará aumentar os dois - todo plano de execução precisará ser recompilado e, se as estatísticas forem obsoletas, talvez você não obtenha os planos mais eficientes. Isso também significa que os dados terão que ser lidos na memória do disco, enquanto antes da reinicialização provavelmente estavam zumbindo junto com os dados da memória. Isso deve durar pouco.
Aaron Bertrand
@AaronBertrand Tem sido assim por oito horas. Nós reinicializamos regularmente o servidor para aplicação de patches e nunca notamos algo assim antes.
Bob Tway
11
Não use a interface do usuário para verificar as configurações. SELECT * FROM sys.configurations;- você quer value, value_in_usecoisas assim max server memory (MB). Além disso, o número da compilação SELECT @@VERSION;seria útil, bem como se isso está em um hipervisor e se alguma coisa mudou no host desde ontem (ou desde a última vez que o SQL Server foi reiniciado).
Aaron Bertrand
2
Que tipo de subsistema de E / S você está usando? SAN, disco local, etc? Existe alguma chance de você coincidentemente ter um disco estragado? Também existem alguns de seus bancos de dados armazenados no mesmo local que qualquer arquivo do sistema operacional? E última pergunta. Parte do nosso processo antes de fazer uma atualização do sistema operacional era tirar um instantâneo da VM com antecedência. Infelizmente, a pessoa responsável esqueceu de cometer. Muito rapidamente, todo o sistema ficou cada vez mais lento. Alguma chance de isso ter acontecido com você?
197 Kenneth Fisher

Respostas:

3

Pode acontecer que uma pequena quantidade de dados atinja um determinado limite no SQL Server para forçar outro plano ou algo assim. Isso não é improvável. Mas o fato de seu disco parecer estar pesadamente sob serviço me leva a outra conclusão.

Existem 2 razões básicas possíveis para o seu abrandamento.

  1. Você atualizou seu sistema e o reinicializou
  2. Você carrega um monte de dados nele

Vamos dar uma olhada na parte nº 1

Pode ser que sua configuração do SQL Server esteja quebrada. Isso pode causar sérios problemas em relação à velocidade do servidor e ao uso do disco.

Por favor, verifique na primeira instância as configurações básicas do servidor. Essas configurações básicas são max server memory,affinity I/O mask , affinity maske max degree of parallelism. Pode ser necessário ativar as opções avançadas usando show advanced options.

Aqui está um script completo:

-- enable advanced options
EXEC sp_configure 'show advanced options',1
-- apply configuration
RECONFIGURE
-- how much memory can the sql server allocate?
EXEC sp_configure 'max server memory'
-- which cpu is used to run I/O operations
EXEC sp_configure 'affinity I/O mask'
-- which cpus can run processes?
EXEC sp_configure 'affinity mask'
-- how many threads can work on one query part?
EXEC sp_configure 'max degree of parallelism'

Compare o resultado com seus valores documentados em suas etapas de instalação. Eles ainda são os mesmos?

Pode haver muitos motivos pelos quais o servidor se comporta de maneira estranha. Eu normalmente apostaria que seumax server memory está errado. Isso fará com que o SQL Server troque permanentemente as páginas de dados. Ele não pode guardar tudo em sua memória. Isso significa que ele precisa ler as páginas do disco, atualizá-lo e escrevê-lo instantaneamente. Se outra atualização aparecer e usar a mesma página para uma atualização, ela não poderá ser lida na memória. Em vez disso, o servidor precisa lê-lo novamente no disco. Apenas trocando ...

Outro problema pode ser uma alta afinidade no disco ou nos processos. Se você usou um servidor compartilhado (SQL Server + outros serviços) com um disco dedicado para o SQL Server (que pode ser um caso raro, mas pode ser), esse pode ser o seu problema. Seu servidor costumava ter, por exemplo, 3 cpus para processos e um para E / S. Os outros 12 cpus são usados ​​para outros serviços. Nesse caso, sua máscara de afinidade está errada e usa, por exemplo, uma configuração automática. Isso significa que o servidor utiliza todos os 16 núcleos para processos e E / S dinamicamente. Se você tiver grandes processos em execução, eles podem colocar uma carga enorme no disco, o que pode não ser possível. Mas, na verdade, não acredito que este seja o seu caso. Seria mais rápido (mesmo que apenas um pouco) se isso se aplicasse, mas o seu caso é mais lento.

Outro problema pode ser um alto grau de paralelismo. O que significa que você tem muitos threads ociosos em uma parte parcial de uma consulta. Isso também pode causar uma grande desaceleração se o paralelismo não funcionar como esperado. Mas isso não descreverá sua E / S alta no total.

Agora vamos dar uma olhada na parte n ° 2 também

Você carrega várias linhas no seu sistema. Mesmo que esse seja um trabalho regular, ele pode aumentar um limite no qual seus planos de consulta aumentam. Pode até ser o caso de sua inserção em combinação com o SQL Server produzir esse comportamento.

Você mencionou que já tentou migrar seus índices para outro disco, o que parece ajudar. Isso pode acontecer apenas pelo fato de você dividir a carga em dois discos diferentes.

Pode ser que seus índices estejam fraturados, que seus planos estejam fraturados ou que suas estatísticas estejam desatualizadas.

1. permite verificar a última atualização das estatísticas Você pode fazer isso manualmente na interface para cada elemento estatístico. O que seria uma dor. Ou você pode tentar este código:

SELECT name AS indexname,
STATS_DATE(OBJECT_ID, index_id) AS StatsUpdated
FROM sys.indexes

Isso fornecerá informações completas sobre cada índice (e pilha) e as estatísticas por trás deles. Mesmo se você executar sp_updatestats, isso não significa que as estatísticas foram atualizadas. A parte em que uma atualização é bastante complicada, mesmo se você executar sp_updatestatsou mesmo se auto update statisticsestiver ativado, as estatísticas não serão atualizadas a tempo. Aqui estão alguns pontos de vantagem, quando uma atualização é necessária / gerada:

  • Uma tabela vazia obtém uma ou mais linhas
  • Uma tabela com mais de 500 linhas atualiza 20% + 500 linhas adicionais e ocorreu uma inserção depois
  • Quando 500 linhas foram alteradas em uma tabela que contém menos de 500 linhas

Isso significa que suas estatísticas podem estar desatualizadas, mesmo se você executar a atualização.

Você pode dar uma olhada na consulta acima. Se você encontrar algumas estatísticas bastante antigas em algumas tabelas, convém executar uma atualização estatística manual para esta tabela:

UPDATE STATISTICS dbo.YourBadTable WITH FULLSCAN

Depois disso, você pode dar um chute no seu servidor para jogar fora todos os planos antigos.

DBCC FREEPROCCACHE 

Se você deseja limpar todos os caches, execute o seguinte:

DBCC FREESYSTEMCACHE ('ALL')

Isso limpará todos os caches, não apenas o cache do plano. Eu normalmente alertaria para usar isso em um servidor de produção na fase de produção. Mas como seu servidor não funciona atualmente, você não pode prejudicá-lo demais. Pode ficar lento por alguns segundos, talvez de 1 a 2 minutos, pois ele precisa reconstruir todos os caches, mas depois disso ele deve executar os planos corretos.

Outro motivo pode ser índices totalmente fragmentados. Isso pode ser verificado em todo o servidor usando esta instrução:

SELECT * 
FROM sys.dm_db_index_physical_stats (NULL, NULL, NULL, NULL, NULL)

Se a fragmentação for muito alta, talvez seja necessário reorganizá-la (fragmentação <20%) ou reconstruí-la totalmente (> 20%). Isso pode levar mais pressão ao seu disco e causar problemas. Por outro lado, se os índices forem tão ruins, provavelmente ajudaria no final mais do que prejudica.

Além desses dois motivos, ainda pode haver um terceiro problema

Talvez o servidor esteja configurado provavelmente, você não alterou nenhum código neste momento, apenas adicionou algumas linhas. Todas as estatísticas são atualizadas e todos os caches são reconstruídos. Todos os seus índices são reorganizados da maneira que você precisa, mas ainda assim - nada funciona. Pode ser que você tenha atingido o limite de memória disponível em seus processos. Talvez você precise de mais. Você pode simplesmente verificar se existe algum processo que tente obter mais memória do que você possui.

Você pode verificar isso usando este comando:

SELECT * FROM sys.dm_exec_query_memory_grants

Ele fornecerá uma lista de todas as sessões que consumem memória. Pode haver alguma consulta que ainda esteja aguardando para obter memória. Essas consultas podem ser facilmente filtradas. Todas as sessões onde granted_memory_kb IS NULL. São sessões que solicitaram memória, mas não a obtêm. Outra coisa pode ser uma memória concedida que pode estar muito baixa. Você pode comparar as colunas requested_memory_kbcom granted_memory_kb. Solicitado mostra quanta memória o processo precisa executar ideal, enquanto concedido mostra a memória que está habilitada para o processo. Se um processo precisar de 2 GB para ser executado, mas obtiver apenas 2 MB ... você poderá obtê-lo por conta própria. ;-)

Outra maneira é verificar o RESSOURCE_SEMAPHORE:

SELECT * FROM sys.dm_exec_query_resource_semaphore

Você pode dar uma olhada no waiter_counte no grantee_count. Se o garçom estiver acima de 0, você pressionará sua memória, o que pode causar trocas e causar a pressão do disco vista por você no perfmon.

Ionic
fonte
0

Além de possíveis falhas na unidade, verifique o estado do seu subsistema RAID. Vimos algo parecido e a bateria do controlador RAID acabou por falhar, portanto não havia cache de gravação disponível - todas as gravações tinham que ir diretamente para o disco. Uma observação lateral - podemos sentir a pausa do sistema enquanto o RDC entra nele.

William Jens
fonte