lunes, 22 de septiembre de 2008

Corrompiendo una BD (parte I) y solucionando el error

Herramientas que necesitamos:
-SQL Server 2005 (en SQL Server 2008 todavía no lo he probado).
-Heditor hexadecimal (en mi caso utilizo XVI32, es freeware)

El error que os voy a describir es de fácil solución, puesto que vamos a corromper un índice nonclustered, pero puede serviros a la hora de practicar posibles soluciones a un error y posiblemente para alguna cosilla más xDDD.

Lo primero de todo es crearos una BD, en mi caso la he llamado Corrupta, estableciendo sobre ella que no verifique ningún error a nivel de página (ALTER DATABASE Corrupta SET PAGE_VERIFY NONE), y después nos creamos una tabla X sobre la que crearemos un índice nonclustered único. A continuación introducimos una serie de registros, en nuestro caso 9 registros.


Ahora veamos, ¿qué es lo que necesitamos? (empezar por algún lado).
Necesitamos saber la página dónde está nuestro índice nonclustered, ¿cómo podemos obtenerla?



si os fijáis en los recuadros en rojo (ese pulso). Veréis que os indico el id del índice (tipo 2 significa nonclustered) y la dirección de la primera página donde se aloja.
Ahora bien, rebuscando un poco he encontrado que Kalen Delaney's tiene una función mediante la cual podemos transformar una dirección hexadecimal en una página:

create function [dbo].[convert_page_nums] (@page_num binary(6))
RETURNS varchar(11)
AS
BEGIN
RETURN(convert(varchar(2), (convert(int, substring(@page_num, 6, 1)) * power(2, 8)) +
(convert(int, substring(@page_num, 5, 1)))) + ':' +
convert(varchar(11),
(convert(int, substring(@page_num, 4, 1)) * power(2, 24)) +
(convert(int, substring(@page_num, 3, 1)) * power(2, 16)) +
(convert(int, substring(@page_num, 2, 1)) * power(2, 8)) +
(convert(int, substring(@page_num, 1, 1)))) )
END
La utilizaremos para convertir nuestra dirección en algo más entendible
SELECT dbo.convert_page_nums(0x7E0000000100)

que nos da como resultado en mi caso la página (1:126)
Para comprobar que es correcto podemos ejecutar
DBCC IND(Corrupta, Datos, -1) (esta instrucción no está documentada en los BOL, podéis encontrar info en el blog de sqlserverstorageengine)
que nos muestra como resultado lo siguiente:



os remarco en rojo la información relevante, la página, el id del índice y el tipo de página.

Después de toda la información que hemos recabado tenemos que hacer un volcado de los datos que contiene esa página, ¿cómo? (sigue leyendo que esto se pone interesante)
Primero activamos la visualización del DBCC PAGE en pantalla mediante:
DBCC TRACEON(3604, -1)
GO
Y después obtenemos el volcado de los datos de la página
DBCC PAGE(Corrupta, 1, 126, 1)
Una vez tenemos los datos nos tenemos que fijar en el Slot 0, que nos indica la primera fila en la página, y en el Slot 8 que nos indica la última página.

Slot 0, Offset 0x60, Length 14, DumpStyle BYTE
Record Type = INDEX_RECORD Record Attributes =
Memory Dump @0x4E85C060
00000000: 06312020 20205a00 00000100 0000††††††.1 Z.......


Slot 8, Offset 0xd0, Length 14, DumpStyle BYTE
Record Type = INDEX_RECORD Record Attributes =
Memory Dump @0x4E85C0D0
00000000: 06392020 20205a00 00000100 0800††††††.9 Z.......

Una vez tenemos estos datos es hora de parar nuestro instancia de SQL Server y abrir en el editor hexadecimal el fichero Corrupta.mdf, acto seguido buscaremos la primera aparición de la cadena hexadecimal 06312020 20205a00 00000100 0000

Ahora cambiaremos los datos por el valor 00 y guardaremos el fichero.

podría haber continuado hasta el último slot pero es un coñazo con este editor o todavía no lo domino lo suficiente (xDDD).

Volvemos a iniciar nuestra instancia y ejecutamos una comprobación de la BD
DBCC CHECKDB('Corrupta') que nos muestra el siguiente resultado:

Resultados de DBCC para 'Datos'.
Mens. 8928, Nivel 16, Estado 1, Línea 1
Id. de objeto 5575058, Id. de índice 2, Id. de partición 72057594038845440, Id. de unidad de asignación 72057594043957248 (tipo In-row data): no se pudo procesar la página (1:126). Vea otros errores para obtener información detallada.
Mens. 8941, Nivel 16, Estado 55, Línea 1
Error de tabla: Id. de objeto 5575058, Id. de índice 2, Id. de partición 72057594038845440, Id. de unidad de asignación 72057594043957248 (tipo In-row data), página (1:126). Error de prueba (dbccAuditRecSucceeded == TRUE). Zona 0, el desplazamiento 0x60 no es válido.
Hay 9 filas in 1 páginas para el objeto "Datos".
CHECKDB detectó 0 errores de asignación y 2 errores de coherencia en la tabla 'Datos'. (Id. de objeto 5575058).

Y al final de todo:
CHECKDB detectó 0 errores de asignación y 2 errores de coherencia en la base de datos 'Corrupta'.
repair_allow_data_loss es el nivel mínimo de reparación para los errores detectados por DBCC CHECKDB (Corrupta).
Ejecución de DBCC completada. Si hay mensajes de error, consulte al administrador del sistema.

¿Bien y ahora qué? la reparamos mediante un REPAIR_REBUILD, REPAIR_ALLOW_DATA_LOSS, restauramos una copia de seguridad.
Lo primero que podríamos hacer es verificar el objeto que tiene el error y para eso lo podemos hacer de la siguiente manera:

SELECT object_name(object_id)AS 'Table',name,index_id,type_desc FROM sys.indexes
WHERE object_id = '5575058'
AND index_id = 2
que nos devuelve los siguientes datos:
Table name index_id type_desc
--------------------------------------------------
Datos SK_Datos 2 NONCLUSTERED
Yuhu, es un índice nonclustered (que novedad si no fuera porque os lo he dicho y lo hemos creado :-)), lo mejor de todo es que al ser nonclustered podremos reconstruirlo mediante la sentencia

ALTER INDEX SK_Datos ON dbo.Datos REBUILD
Una vez hecho esto volvemos a ejecutar un DBCC CHECKDB('Corrupta')

CHECKDB detectó 0 errores de asignación y 0 errores de coherencia en la base de datos 'Corrupta'.
Ejecución de DBCC completada. Si hay mensajes de error, consulte al administrador del sistema.
y voilà los errores de consistencia han desaparecido, nos hemos quitado un marrón (dolor de cabeza, o como lo quieras llamar) de encima y nos quedamos satisfechos de nuestro trabajo realizado.
Bueno eso es todo amigos, espero os guste y os sirva para salir de un apuro. Saludos y hasta pronto.

BD's con más consumo de I/O

--Bases de datos que utilizan más I/O
--BD, Tipo de fichero, IO en megas, IO Stall en segundos (tiempo de espera para lectura o escritura), Porcentaje de IO stall, Posición de más a menos IO Stall (Ranking)

WITH Consumo AS
(
SELECT DB_NAME(IV.database_id) AS db, CASE WHEN MF.type = 1 THEN 'log' ELSE 'data' END AS file_type, SUM(IV.num_of_bytes_read + IV.num_of_bytes_written) AS io, SUM(IV.io_stall) AS io_stall
FROM sys.dm_io_virtual_file_stats(NULL, NULL) AS IV JOIN sys.master_files AS MF ON IV.database_id = MF.database_id AND IV.file_id = MF.file_id
GROUP BY DB_NAME(IV.database_id), MF.type
)
--si no queremos verlo en segundos podemos modificar el io_stall /1000 para verlo en milisegundos, etc
SELECT db, file_type, CAST(1. * io / (1024 * 1024) AS DECIMAL(12, 2)) AS io_mb, CAST(io_stall / 1000. AS DECIMAL(12, 2)) AS io_stall_s, CAST(100. * io_stall / SUM(io_stall) OVER() AS DECIMAL(10, 2)) AS io_stall_pct, ROW_NUMBER() OVER(ORDER BY io_stall DESC) AS rnk
FROM Consumo
ORDER BY io_stall DESC;

Avisaros que en SQL 2000 no os funcionará ya que utiliza DMV de SQL Server 2005

viernes, 12 de septiembre de 2008

BD Sospechosa y SQL Server 2008

Gran puntazo a favor de SQL Server 2008!!! Ya no podemos separar por error o desconocimiento una base de datos en estado sospechoso, os adjunto una captura de un futuro post que estoy preparando: (cómo bien reza, sólo podemos repararla o quitarla (DROP :-)), muhahaha)

lunes, 8 de septiembre de 2008

Errores en la web

Errores tontos como diría un compañero, que también tiene su blog personal. Petada al canto al intentar ver más vídeos en la peich de JumpStartTV. La verdad es que tiene vídeos interesantes pero la navegación deja mucho que desear.
Seguro que cuando vean la petada al que se le olvidó poner el Try Catch no se le vuelve a olvidar xDDD.




Bueno aún no han corregido el error (13/09/2008) pero la petada ya no es evidente para los demás, parece ser que el Try Catch ha funcionado

viernes, 5 de septiembre de 2008

Resolución de problemas relacionados con Tiempo de Espera agotado

Buscando y rebuscando en los libros en pantalla (sí no tengo otra cosa mejor que hacer ;-) y os sorprenderíais de la documentación que nos aportan y que mucha gente desconoce), he encontrado la solución que nos aporta Microsoft para solucionar los problemas de tiempo de espera agotado al intentar conectar desde nuestra aplicación contra el servidor que contiene la BD.
A muchos os puede parecer lógico o algo fácil, pero seguro que alguien en algún momento lo ha sufrido y ha tenido que buscar información al respecto (verdad Berni ;-) ).
Bueno no me enrollo más y os pongo el link a los BOL

ms-help://MS.SQLCC.v10/MS.SQLSVR.v10.es/s10de_4deptrbl/html/ad6e3f43-7d0b-4d6c-ab2a-038a5a3b2690.htm

y en internet

http://msdn.microsoft.com/es-es/library/ms190181.aspx

Reconstruir las Bases de Datos de sistema en SQL Server 2008

Más conocido como “Rebuild master”. Para hacerlo debemos seguir los siguientes pasos:

1.- Abrimos una consola de msdos y nos situamos en la carpeta dónde tenemos instalado SQL Server 2008 en nuestra máquina, en mi caso C:\Program Files\Microsoft SQL Server\100\Setup Bootstrap\Release

2.- Ejecutaremos Setup.exe con las siguientes opciones, si tenemos activado el modo de autenticación usaremos la siguiente sintaxis:

Setup /ACTION=REBUILDDATABASE /QUIET /INSTANCENAME= /SQLSYSADMINSACCOUNTS=

habrá que sustituirlo por el nombre de nuestra instancia o MSSQLSERVER en caso de que sea la instancia por defecto

son los grupos de Windows o cuentas individuales.

Si tuviéramos configurado el modo de autenticación mixta usaríamos la misma sintaxis añadiendo la opción /SAPWD para especificar la contraseña del usuario SA. Si no lo hacemos nos daría un error.

Si quisiéramos reconstruir las bases de datos de sistema con una intercalación diferente a la usada en la instalación de SQL Server, necesitaremos especificar el parámetro /SQLCOLLATION. Si omitimos el parámetro entonces se reconstruirán con la intercalación que utilizamos en la instalación de SQL Server.

3.- Cuando termine el setup de reconstruir las bases de datos, retornará al prompt sin dar ningún aviso. Si sucediera algún error este se visualizaría en el prompt. En el caso de que no viéramos errores podríamos dar un vistazo al log “Summary”.

4.- Los log se almancenan en \100\setupbootstrap\logs, podemos revisarlo abriendo el fichero Summary.txt

Por supuesto todo esto lo podemos hacer si la necesidad de tener el DVD de instalación, lo tenemos todo en \Binn\templates, por ejemplo la ruta en mi equipo es C:\Program Files\Microsoft SQL Server\MSSQL10.SQL2008\MSSQL\Binn\Templates. En este directorio tenemos todas las bases de datos del sistema que se copian en el momento de la instalación. Por lo tanto una vez reconstruyamos las bases de datos tendremos que cogerlas de este directorio y copiarlas en nuestro directorio de datos.
Si en este directorio no tuviéramos estas bases de datos al intentar hacer la reconstrucción nos daría un error.

Si no tuviéramos las bases de datos entonces tendríamos que ejecutar la instalación desde el DVD y seleccionar la opción reparar o bien buscar dentro del DVD la siguiente ruta, dependiendo de si es para una plataforma x86, x64 o ia64:
setup\sql_engine_core_inst_msi\PFiles\SqlServr\MSSQL.X\MSSQL\Binn\Template
y copiarlas bases de datos en la carpeta templates de nuestro equipo. Una vez copiadas las bases de datos, ejecutaremos la reconstrucción con la instrucción que os he dado un poco más arriba.

Otro de los aspectos no mencionados en este ladrillazo es lo siguiente, ¿qué pasa con la base de datos Resource? Muy sencillo, la reconstrucción no vuelve a generar una nueva bd Resource (mssqlsystemresource). Para ello tendremos que ejecutar la instalación desde el DVD y seleccionar la opción Reparar.

miércoles, 3 de septiembre de 2008

Vídeos de SQL SERVER

Leyendo diversos post por la red de un lado para otro cuando el tiempo me lo permite he descubierto un site interesante

http://www.sqlservervideos.com/

Tenemos los vídeos ordenados por temática, también podemos verlos por nivel de dificultad, por el tipo de audiencia (DBA, programador, ...), etc. Por el momento son 15 vídeos que imagino irán creciendo con el paso del tiempo.