Loading…

Casos do Dia a Dia: Corrupção de Dados e Database Suspect

Fala Pessoal,

Gostaria de fazer deste post como se fosse uma thread de um fórum com uma discusão sobre alta disponibilidade no SQL Server.

Sábado, dia 13/08 eu tive um problema em uma database que deixa qualquer DBA com o coração disparado(DBA não pode ter problema cardíaco!!!). Uma database de 110GB que é muito utilizada ficou com o status Suspect. No meu caso não foi tão grave pois o problema ocorreu em uma database de um servidor D-1 que recebe restore diário do servidor de produção.

A database ficou Suspect durante a criação de um índice muito grande que é criado diariamente nesse servidor D-1.

A primeira coisa que fiz para tentar deixar a database online novamente foi seguir os passos desse meu outro artigo, onde já havia recuperado uma database em modo Suspect: Casos do Dia a Dia: Database em modo Suspect.

Então, executei os comandos:
ALTER DATABASE XXXXXX SET EMERGENCY — Foi alterada com sucesso

ALTER DATABASE XXXXXX SET ONLINE

Entretanto, ao tentar deixar a database ONLINE, ela entrou em modo SUSPECT novamente e o erro abaixo foi gerado:

Msg 926, Level 14, State 1, Line 1
Database NOMEDATABASE cannot be opened. It has been marked SUSPECT by recovery. See the SQL Server errorlog for more information.Msg 5069, Level 16, State 1, Line 1. ALTER DATABASE statement failed. Msg 824, Level 24, State 2, Line 1
SQL Server detected a logical consistency-based I/O error: incorrect pageid (expected 1:1175999; actual 1:12045999). It occurred during a read of page (1:11751999) in database ID 99 at offset 0x0000166a370000 in file ‘X:\XXXXXX.mdf’.
This is a severe error condition that threatens database integrity and must be corrected immediately. Complete a full database consistency check (DBCC CHECKDB).

Fiz um select na tabela Msdb.dbo.Suspect_Pages e encontrei 2 páginas com problema. As duas possuíam na coluna Event_Type o valor 1 que significa:

1 = An 823 error that causes a suspect page (such as a disk error) or an 824 error other than a bad checksum or a torn page (such as a bad page ID).

Novamente deixei a database em modo de emergencia para fazer alguns select na database:

ALTER DATABASE XXXXXX SET EMERGENCY

ALTER DATABASE XXXXXX SET SINGLE_USER WITH ROLLBACK IMMEDIATE

Em seguida, eu tentei rodar o comando abaixo para verificar qual seria o objeto que estava com problema, mas o DBCC PAGE retornava um erro e não me mostrava a informação dos objetos:

DBCC TRACEON ( 3604 )
DBCC PAGE ( XXXXXX, 1 , 1175999 , 3 )

ou
DBCC PAGE ( XXXXXX, 1 , 1175999 , 1 )

Nesse momento, tentei rodar o comando DBCC CHECKDB nessa database, mas o mesmo também não funcionou retornando o seguinte erro com 5 segundos de execução:

Msg 8921, Level 16, State 1, Line 2. Check terminated. A failure was detected while collecting facts. Possibly tempdb out of space or a system table is inconsistent. Check previous errors.

Pela mensagem de erro, como a letra do TempDB estava com 30 GB de espaço disponível, acredito que uma tabela de sistema dessa database estava inconsistente.

Como eu não iria voltar um Backup Full pois já estava quase na hora da atualização diária dessa database(o que foi executado com sucesso), fui tentar uma última opção para recuperar a database mesmo com uma possível perda de dados:

DBCC CHECKDB (NOME_DATABASE, REPAIR_ALLOW_DATA_LOSS)

Todavia, esse comando também me retornava um erro:

Msg 8921, Level 16, State 1, Line 2. Check terminated. A failure was detected while collecting facts. Possibly tempdb out of space or a system table is inconsistent. Check previous errors.
CHECKDB found 78 allocation errors and 0 consistency errors not associated with any single object.
CHECKDB found 78 allocation errors and 0 consistency errors in database ‘XXXXXX’.

No log do SQL foi registrada a seguinte informação:

DBCC CHECKDB(XXXXXXX) WITH no_infomsgs executed by LOGIN found 78 errors and repaired 0 errors.

Ou seja, não foi possível corrigir o problema dessa database. Eu apenas consegui deixar a database disponível para uso novamente executando:

ALTER DATABASE XXXXXX SET MULTI_USER

Alguns jobs que acessam essa database até executaram com sucesso, mas eu não consegui criar o índice que gerou o problema de corrupção e acredito outras procedimentos falhariam ao acessar os dados corrompidos.

Eu não consegui encontrar outra solução que não fosse voltar o restore completo dessa database, o que demoraria mais de 1 hora e causaria um grande transtorno se fosse em produção.

Se eu tivesse toda uma solução de cluster do SQL Server, não adiantaria nada nesse caso pois ela garante a disponibilidade do Hardware do servidor.

Minha replicação de dados entre 2 Storages também não resolveria pois os dados iriam corrompidos de um Storage para o outro.

Conforme já tinha verificado na tabela Suspect_Pages, ele me indicou que o erro gerado era de número 823 ou 824:
EventType = 1 :An 823 error that causes a suspect page (such as a disk error) or an 824 error other than a bad checksum or a torn page (such as a bad page ID).

Na solução de Database Mirroring do SQL Serve 2008, temos uma ótima funcionalidade de correção de páginas corrompidas, conforme podemos ver nesse artigo do Paul Randal:SQL Server 2008: Automatic Page Repair with Database Mirroring

Nesse artigo podemos ver os números dos erros que a solução de Automatic Page Repair soluciona:

“The feature works for pages that have 824 errors, 823 errors where the OS returns a CRC error while reading the page (to prevent resource issues triggering a page repair), and pages that have 829 errors (where the page is marked as restore pending).”

Logo, se eu tivesse um Database Mirroring configurado ele resolveria esse meu problema de corrupção de forma transparente.

Contudo, a solução de Database Mirroring também tem alguns problemas:

  • Só faria o failover automático dessa database, mas muitos procedimentos dessa DB dependem de outras DB para funcionar.
  • Ele não faz o mirror de Logins, Linked Server e Jobs que são alterados no servidor Principal.
  • Tem um impacto na performance já que os dados são escritos no mirror antes de serem escritos na database principal.
  • Nem todas as páginas podem ser reparadas com o Page Repair, conforme disse o Paul Randal: “Not all pages can be repaired – the file header page, database boot page, and allocation bitmap pages (GAM, SGAM, PFS) cannot be repaired this way.”

Nós que trabalhamos como DBA Full Time de uma empresa, vamos sempre dormir preocupados pois a qualquer momento pode acontecer um problema em que sua solução de alta disponibilidade não consiga tratar 100% dos possíveis problemas e você precise voltar um backup completo da base, o que dependendo do tamanho da database, causaria um alto tempo de parada (perda de $$) e muitas explicações teriam que ser dadas a diretoria.

Alguém tentaria fazer algo diferente para resolver esse problema específico de corrupção?

Qual solução de High Availability e Desaster Recovery você utilizaria para deixar seu BD (>500 GB de dados) preparado para problemas de hardware e de Corrupção e com um Failover Automático? Não importando o valor do investimento($$) necessário.

Conto com a opinião da comunidade SQL Server.

Gostou dessa dica?

Cadastre seu e-mail para receber novos Posts e curta minha Página no Facebook para receber Dicas de Leituras e Eventos sobre SQL Server.

Confira mais experiências do Dia a Dia de um DBA no meu Treinamento de Tarefas do Dia a Dia de um DBA.

Abraços,

Fabrício Lima

MCITP – Database Administrator

Consultor e Instrutor SQL Server

Trabalha com SQL Server desde 2006

13 thoughts on “Casos do Dia a Dia: Corrupção de Dados e Database Suspect

  1. Fabricio,

    Se dinheiro nao fosse problema colocaria raid 10 em tudo e minha solução de alta disponibilidade seria Cluster + Database Mirroring, acho essa abordagem bem interessante.

    Sobre a pagina corrompida, tentaria pegar o backup FULL e com isso restaurar somente essa pagina.

    Uma opçao para o Database Mirroring seria a de High Performance o failover é manual, mas as transações são enviadas de forma assincrona para o mirror.

    Abraços,
    Marcos Freccia

    1. Valeu Marcos,

      Eu poderia mesmo ter feito o teste de restauração dessa página.

      Também acredito que essa solução seja a muito boa(cluster + mirroring). Acredito que não temos como ficar sem um database mirroring devido a essa solução de PAGE REPAIR.

      Sobre o Database Mirroring em High Performance, o problema é que poderíamos ter perda de dados nesse caso. Não seria 100% garantido.

      Abraços

      1. E também custaria horrores, pois essa opção somente pode ser utilizada na edição Enterprise. Com dinheiro, seria muito fácil… Mas como sabemos, a maioria das empresas não querem fazer investimentos altos em TI.

  2. Fabricio,

    Isto aconteceu em discos locais? Porque um erro de disco como teria probabilidade 0% em um ambiente com storage confiavel em RAID 50 ou 60, já que o storage não permitiria a corrupção de dados.

    Em sistemas críticos implementamos RAID 0+1 de storages com snapshot dinâmico, que garante restore imediato no nivel do hardware, similar ao Shadow Copy do Windows.

    Um abraço.

    1. Fala Marcelo,

      Essa database fica em um Storage com RAID 5.

      “Em sistemas críticos implementamos RAID 0+1 de storages com snapshot dinâmico, que garante restore imediato no nivel do hardware, similar ao Shadow Copy do Windows.”
      Nesse caso, se uma página da database se corromper ela irá ser replicada corrompida pelo snapshot, não?

      Obrigado pelo comentário.

      1. Oi Fabricio,

        Não porque o motivo do suspect no banco que vc relatou foi corrupção no disco, e neste caso os RAIDs não deixariam acontecer.
        E mesmo que acontecesse por erro do próprio engine do SQL, o que é dificil de acontecer, com o snapshot vc poderia recuperar o dado rapidamente como um restore de PAGE.
        Como você indicou que o erro foi durante um uso intensivo de disco ao criar indice, o erro muito provavelmente foi devido a problema de disco, talvez alto consumo com concorrencia em processos.
        Não vejo motivos de ter sido o engine do SQL pois neste caso você teria travamentos em outras ocasiões.

        Um abraço.

  3. Fabricio,
    Desde que comecei a trabalhar com banco de dados SQL Server. Peguei cinco casos de corrupção de dados e todos em produção. 🙁 Conseguir resolver os cinco e cada um foi um solução diferente. vou citar dois casos:

    1. Um dos casos, resolvi sem nenhuma atividade em banco de dados. apenas realizando uma verificação nos disco. Perguntei ao cara do “CPD” se tinha acontecido algo e ele falou que houve queda de energia e o Nobraker não segurou.
    2. O outro caso foi uma base do SQL Server 7 onde tive que reparar manualmente um tabela do sistema. As colunas e tipos de dados estavam trocados e os tipos não batiam com os tipos fisicos no arquivo de dados. A solução como falei foi reconstruir manualmente a tabela de sistema.

    Na minha opnião o maior problema de corrupção de dados está em falhas de hardware, ou melhor no mau dimencionamento dos recursos sejam eles storages, Nucleos, switch, Servidores…

    obs.; Utilizar disco locais para bases de dados é um grande risco. Então excluo os Disco locais como recursos para banco de dados. em um queda de energia os discos são os primeiros a perderem a força e por consequencia a rotação.

    Você pode ter a melhor solução Cluster, Mirroing ou storage mas se você não dimensionar os circuitos de força, Nobrakes e Geradores. Seus dados correm grande perigo.! Mais cedo ou mais tarde a corrupção de dados baterá a sua porta. Lembre-se: “tudo em computação é corruptivel.”

    O que fazer para eliminar;(pelo menos para mim!)

    1. Bom circuito de instalação da força (Dimencionamento da força).
    2. Storage confiavel com um bom cache de dados e boas praticas.
    3. Circuitos de rede confiavel (cabos,switch, Nucleo…)
    4. Servidores com um bom SO e sistema de arquivo confiavel.
    5. Nobraker para picos\baixas de energia(Filtros). (Carga de uma hora)
    6. Geradores para assumir o circuito de força e refrigeração em caso de queda de energia por mais de 30 minutos.

    Como a corrupção é algo sempre presente, com a estrutura acima você consegue evitar corrupção de bases em 99,9999%. No ambiente atual onde trabalho em três anos nunca tivemos um corrupção nas mais de 500 bases de produção.

    1. Muito obrigado pelo seu feedback Leivio,

      A database que corrompeu estava conectada em um Storage EMC CX310 e o CPD onde eles estão possui Nobrakes e um Gerador onde já ficamos horas sem energia e nenhum servidor parou por nenhum segundo.
      Coincidentemente, o problema aconteceu na hora de uma criação de um índice muito grande, o que aloca muitas novas páginas. E não houve nenhum registro de queda de energia. Caso o hardware do servidor não esteja aguentando a carga de trabalho, isso pode influenciar?

      No caso desse meu problema, acredito que não tinha o que fazer a não ser um restore de páginas no mínimo, concorda?

      Abraços

  4. Eu não sou tão experiente a ponto de determinar o que poderia solucionar este seu caso, mas acredito que uma solução que pode ser criada para databases que são realmente críticas para o negocio é conciliar o uso de Cluster de Failover com Log Shipping. Digo isso por que, usando o cluster de failover, garantimos a disponibilidade da instância inteira, e com o log shipping podemos retornar rapidamente uma database a um estado “integro”. Apesar de que no seu caso, se fosse em base de produção, usando a solução que descrevi ocorreria perda de informações. Pensei neste cenário, pois a replicação estaria com o mesmo problema, já que o assinante teria a replica igual ao publicador…

    Espero ter contribuido.

    Abraço!

    1. Obrigado pela contribuição Giovani.

      Concordo com o Cluster. O problema do Log Shipping é que pode acontecer perda de dados. Diferente do Database Mirroring que garante que os dados do mirror estão 100% sincronizados com o Principal.

      Abraços

  5. Como fazer isso ?
    Sobre a pagina corrompida, tentaria pegar o backup FULL e com isso restaurar somente essa pagina.

    Faria o restaure em outra base droparia a tabela com os dados corrompidos e criaria a tabela com base do restaure ?

Deixe uma resposta