Corrupción... ¿Que hacer? (Parte 2)


En el primer post no se realizaron muchas acciones en tiempo real, la mayoría fue como detectar anticipadamente y un poco de cómo reaccionar a la misma pero supongamos ahora que tenemos una base en suspect, recovering, recovering pending o simplemente la gente se queja de lentitud y fallas pero ya rehicimos indices, estadísticas, revisamos los queries y nada solventa el problema.

Dependiendo de tu RPO (que tanto toleras perder) y RTO (que tanto puedes tener la base fuera de linea), talvez la mejor opción sea perder datos y repararla para tenerla arriba lo mas rápido posible. En todo caso debo de tocar dos puntos importantes si van a pedir ayuda a Microsoft, Microsoft no es una empresa de recuperación de desastres y no puede garantizar recuperar tu información y aún programas en la red o empresas de recuperación serán lentos y costosos los cuales en el mejor de los casos tendrán pérdidas de información y la información no será consistente. Recuerda si no sabes hacer esto y no tienes un backup pide ayuda.

Ahora bien si optamos por esto lo primero a saber es que tipo de error tenemos, no podemos reparar algo que no sabemos qué es.

Para esto SQL Server cuenta con un comando llamado checkdb, el cual ya lo vimos en post anteriores en la tarea de mantenimiento de integridad de datos.

Este comando lo que hace es revisar las alocaciones y las tablas de sistema y puede llegar tardar bastante si la base es grande para eso mismo tenemos.
  • Checktable: Que como el nombre indica verifica la tabla y sus indices
  • Checkcatalog: Que verifica la metadata
  • Checkkfilegroup: Que verifica todos los archivos e información en el filegroup
Es importante saber esto porque cuando la base es muy grande el checkdb hace todos estos internamente, si la base esta funcionando y suponemos que existe corrupción podemos ir tabla por tabla o por filegroup buscando la corrupción

Lo que hace es:
  • Revisión primitiva de las tablas de sistema
  • Revisión de alocación
  • Revision logica de tablas de sistemas
  • Revision logica de todas las tablas
  • Revisión de metadata
  • Validación de service broker 
  • Indices
El codigo que yo recomiendo ejecutar seria

1
2
DBCC TRACEON(3604)
DBCC CHECKDB (yourdb) WITH ALL_ERRORMSGS, NO_INFOMSGS

Existen algunas opciones importantes como:
  • Datapurity: Normalmente solo usada cuando existen migraciones al hacer un upgrade in place, busca por datos fuera de rango, este tipo de errores no pueden ser corregidos automáticamente aunque son de poco impacto ya que con un update sobre el registro el error puede ser corregido al pasarlo a un valor adecuado.
  • Tablock: En caso en vez de hacer una snapshot en la tempdb usará la misma tabla la cual podrá ser accesada pero el desempeño decaerá.
  • Physical_only: No hace las comprobaciones lógicas lo cual hace mas rapido la revisión pero menos viable es una opción en sistemas con bases muy grandes aunque buscar una ventana para revisiones completas cada n meses es lo recomendado.
  • All_errormsgs: En algunas versiones solo nos da 200 errores, con esto obtendremos el listado completo de los mismos.
  • No_infomsgs:: Eliminar los mensajes que no contienen errores y solo son informativos.
Una vez hecho por favor esperen que el proceso termine ya que si lo interrumpen hará un rollback y puede demorar mas tiempo del que ya lleva en ese momento.

Si el dbcc checkdb o alguno de sus derivados no empieza o presenta alguno de estos errores la base es irrecuperable y deben restaurar de un backup.
  • El dbcc no puede iniciar
  • Errores 7984 y 7988: en tablas de sistema
  • Error 8967: Estado inválido del checkdb 
  • Error 8930: Corrupción en la metadata 
  • Errores en las paginas:
    • 0 header page
    • 9 boot page
    • 17 metadata page
Sino sale nada de esto al final te dira cual es nivel mínimo de ejecución para posible reparación siendo "repair_rebuild" o "repair_allow_data_loss".

Si la opción que te da es un "repair_rebuild" es seguro que sea un no clustered index el que este dañado o algo que no causará pérdida de datos, si el indice que te da es mayor a 1 es una buena indicación de que es un índice non clustered.

Para reparlo puedes usar

1
2
3
ALTER DATABASE master SET SINGLE_USER
GO
DBCC CHECKDB(master, REPAIR_REBUILD)

Aunque esto forzará pasar la base a single user mode por un rato, otra opción será.

1
2
ALTER INDEX 'name' ON 'table' disable
ALTER INDEX 'name' ON 'table' rebuild

Lamentablemente esta operación no sirve con online index rebuild de la versión enterprise de 2012 en adelante.

En caso de que la opción que nos de sea "repair_allow_data_loss" debemos estar conscientes de que borrara las paginas dañadas, esto implica
  • Ignora constraints
  • Ignora lógica de negocio en lo borrado (no habrá borrado en cascada)
  • Replicación
  • No sabemos que borrara ni cuanto afectará
La sentencia en estos casos:

1
2
3
ALTER DATABASE master SET SINGLE_USER
GO
DBCC CHECKDB(master, REPAIR_ALLOW_DATA_LOSS)

En ningun momento hago recomendación de ella pero se que es la ultima alternativa en ocasiones.

Recordemos que debemos de devolver la base a multi user una vez terminada el checkdb si es que se pudo reparar.

1
ALTER DATABASE 'nombre' SET MULTI_USER

Más información

Comentarios

Entradas más populares de este blog

Mover indices no clustered a un nuevo filegroup