Falló el DBCC CHECKDB, y ahora que hacemos?

Posted on
  • lunes, 31 de enero de 2011
  • by
  • Román
  • in
  • Etiquetas: , , , ,

  • Que pasaría si encontraras un error en los logs indicando que tenés un error de los siguientes: torn page o checksum error. Que hacemos??
    Que hacemos?

    La mayoría en realidad no tiene ni idea de que es lo que hay que hacer. Que harías en esa situación en que un error de consistencia se ha detectado en una de las bases que tu (tu) administras?

    La respuesta pasa por usar DBCC CHECKDB diariamente para detectar errores de consistencia.

    La sintaxis básica es:

    DBCC CHECKDB ('Nombre de SU base') WITH NO_INFOMSGS

    NO_INFOMSGS previene que se disparen un número excesivo de mensajes, de todas maneras hay muchas opciones, pero esta realiza los chequeos mínimos necesarios.

    Esta sentencia puede tomar un tiempo importante en ejecutarse si las bases de datos son grandes y en ese caso quizás pudiera querer especificar la opción PHYSICAL_ONLY, ya que esta opción chequea fisicamente en las estructuras en disco, pero omite los chequeos lógicos:

    La sintaxis es:

    DBCC CHECKDB ('Nombre de SU base') WITH PHYSICAL_ONLY

    Ok, hay un problema y... ahora?

    Siempre asumimos la existencia de los backups, no?. Todos sabemos que un indice non-clustered puede ser reconstruido sin mayores problemas, pero un indice clustered no.

    La mejor opción es siempre recuperar desde un backup (en realidad siempre lo mejor es tener implementada una opción de alta disponibilidad tipo cluster o mirroring y el backup mantenerlo solamente como opción B, pero bueno, supongamos que tenemos que ir a los backups).

    Primero vamos a ver que páginas están dañadas y que tipo de datos son los que están dañados (recuerdan clustered y non-clustered?)

    Para empezar veamos que nos dice DBCC CHECKDB, por ejemplo una salida típica puede ser la siguiente:

    Object ID 2088535921, index ID 0, partition ID 72345201021503994, alloc unit ID 72345201051571606 (type In-row data): Page (1:95555) could not be processed. See other errors for details.
    Msg 8939, Level 16, State 98, Line 1
    Table error: Object ID 2088535921, index ID 0, partition ID 72345201021503994, alloc unit ID 72345201051571606 (type In-row data), page (1:95555). Test (IS_OFF (BUF_IOERR, pBUF->bstat)) failed.
    CHECKDB found 0 allocation errors and 2 consistency errors in table 'SU_tabla' (object ID 2088535921).
    CHECKDB found 0 allocation errors and 2 consistency errors in database 'SU_base_de_datos'.
    repair_allow_data_loss is the minimum repair level for the errors found by DBCC CHECKDB (SU_base_de_datos).

    Acá ya sabemos cual es la página corrupta: (1:95555)

    Ahora necesitamos saber si los datos están en un montón (heap), en un indice cluster o en un índice non-clustered.

    Entre los datos podemos ver que es index ID 0. Podemos examinar especificamente la página (1:95555 en 'SU_base_de_datos') como vemos a continuación:

    DBCC TRACEON (3604, -1)
    GO
    DBCC PAGE('SU_base_de_datos', 1, 95555, 3)
    GO

    En la salida vamos a ver algo como:

    Metadata: IndexId = n

    Si n es mayor a 1 entonces puede festejar ya que se trata de un índice non-clustered que puede ser borrado y recreado.
    Ahora bien, si es 0 o 1 entonces ya se trata de corrupción de datos directamente y vamos a tener que hacer de lo que describiremos mas abajo.

    RECUPERAR DESDE UN BACKUP

    Si el "recovery model" es FULL entonces usted hará un backup de tail log (si no sabe que es un tail log backup recuerde google es nuestro amigo).
    Entonces, tail log backup, restore full backup, differential backups, logs backups, etc, etc todos con la opción WITH NORECOVERY y finalmente recupere el backup de tail log pero esta vez con la opción WITH RECOVERY.
    Asumo que usted tiene bien en claro los procesos de backup/restore, si así no fuera entonces llamen a un administrador experimentado antes de perder datos y eventualmente su trabajo.

    Si solo fueron afectadas unas pocas páginas entonces tenemos la opción de recuperar solamente las páginas dañadas, como vemos a continuación:

    RESTORE DATABASE SU_base_de_datos PAGE = '1:95555'
    FROM DISK = 'C:\SU_backup.bak'
    WITH NORECOVERY

    Si el "recovery model" está en modo simple, entonces no tiene absolutamente ninguna opción y va a tener que aplicar un procedimiento de restore completo.

    Ahora si usted no tiene absolutamente ningún backup, entonces podría llegar a aplicar la opción de automatic repair. (haga backup de todo por favor)

    OPCIONES AUTOMATICAS DE REPARACION

    Primero: backup, backup, backup. Queda avisado: BACKUP antes de hacer cualquier cosa que se le ocurra hacer.

    Ok, miremos nuevamente la salida de CHECKDB. Ahí se especifica el mínimo nivel de reparación.

    REPAIR_REBUILD
    Si el nivel mínimo de reparación es REPAIR_REBUILD usted debería estar mas o menos feliz.
    La sintaxis es:

    DBCC CHECKDB('SU_base_de_datos', REPAIR_REBUILD)

    REPAIR_ALLOW_DATA_LOSS
    Con esta opción ya no debería estar tan contento.
    Esta opción intentará reparar todos los errores encontrados pero retirará eventualmente la página afectada y modificará los links entre páginas,
    de modo que todo quedará como si esa página nunca hubiera existido. Algo se habrá borrado y habrá que ver que consecuencias a nivel de integridad referencial y perdida de datos esto pueda haber generado.

    La sintaxis es:

    DBCC CHECKDB('SU_base_de_datos', REPAIR_ALLOW_DATA_LOSS)

    Despues asegúrese de ejecutar DBCC CHECKCONSTRAINTS una vez finalizado el checkdb para verificar problemas de integridad referencial que puedan ocurrir y tomar las medidas apropiadas.

    FINALMENTE

    La opción correcta es (en el 99% de los casos) recuperar un backup. Solo usamos las opciones automáticas de recuperación cuando no nos queda absolutamente otra opción.

    DBCC CHECKDB es una herramienta poderosa, pero muy peligrosa en las manos equivocadas, es como un bisturí, que tiene una utilidad en las manos de un cirujano y otra muy distinta en las manos de un chipancé.


    Hugo Román Bernachea
    Mail de contacto: SQLServer777@gmail.com

    Microsoft Certified DBA
    Microsoft Certified Trainer
    Twitter: @bernachea