Mañana asistiré a las charlas programadas en el IV Aniversario del grupo GUSENET (www.gusenet.com). ¡Cómo pasa el tiempo! La verdad es que hace 4 días recuerdo estar en Sta. Pola celebrando el III Aniversario y conociendo a gente maravillosa y dispuesta a ayudar a los demás.
En la web del grupo podréis ver el programa de mañana.
Desde aquí quiero animar a la gente que no conoce el grupo a que acuda a disfrutar tanto de las charlas cómo de la gente que compone el grupo, a exponer sus dudas y a participar en los diferentes eventos que se programan mes tras mes.
Hace poco disfrutamos de dos integrantes del equipo de programación de Visual Basic venidos desde Redmond.
viernes, 28 de noviembre de 2008
Novedades SQL Server 2005 y 2008
Bueno después de estar un tiempo desconectado, he dado un vistazo a las novedades que me he perdido de SQL Server. Para empezar, comentaros que en Septiembre se publicó un CU1 (Cummulative Update) para SQL Server 2008 y hace pocos días se ha publicado un segundo CU2, más en concreto el día 18 de Noviembre (si queréis ver lo que corrige lo podéis ver en http://support.microsoft.com/kb/958186/en-us), recordad que para descargarlo es bajo demanda.
Por otro lado se ha publicado el tan aclamado SP3 para SQL Server 2005 pero en estado BETA, sólo para testeo (se hizo el día 28 de Octubre, sí ya ha llovido desde entonces jejeje, es lo que tiene no estar al día de las cosas, y pensar más en los videojuegos).
Por otro lado se ha publicado el tan aclamado SP3 para SQL Server 2005 pero en estado BETA, sólo para testeo (se hizo el día 28 de Octubre, sí ya ha llovido desde entonces jejeje, es lo que tiene no estar al día de las cosas, y pensar más en los videojuegos).
sábado, 8 de noviembre de 2008
Interfaz de conexión contra una BD C#
Buscando y buscando di el otro día con la interfaz de conexión que utiliza Visual Studio para conectarnos a una BD. Os dejo un ejemplo de cómo implementarlo en un proyecto.
Para poder utilizar esta interfaz necesitamos agregar a nuestro proyecto un par de referencias que tenemos localizadas en el directorio de instalación de Visual Studio bajo la carpeta:
Microsoft Visual Studio 9.0\Common7\IDE\Microsoft.Data.ConnectionUI.Dialog.dll
Microsoft Visual Studio 9.0\Common7\IDE\Microsoft.Data.ConnectionUI.dll
(En este caso para VS2008, en VS2005 también está disponible en su lugar será 8.0 ;P)
Una vez añadidas las referencias necesitamos importarlas mediante:
using Microsoft.Data.ConnectionUI;
Y por último para utilizarlas en nuestro proyecto:
Microsoft.Data.ConnectionUI.DataConnectionDialog dialogo = new Microsoft.Data.ConnectionUI.DataConnectionDialog();
//Añado por defecto las conexiones estándar, podemos seleccionar o limitar el tipo de conexión que mostrará la ventana de conexión.
Microsoft.Data.ConnectionUI.DataSource.AddStandardDataSources(dialogo);
Microsoft.Data.ConnectionUI.DataConnectionDialog.Show(dialogo);
Si queremos obtener la cadena de conexión resultante de los datos introducidos en la ventana de conexión es tan simple cómo asignar a una cadena el resultado de:
dialogo.ConnectionString
Para poder utilizar esta interfaz necesitamos agregar a nuestro proyecto un par de referencias que tenemos localizadas en el directorio de instalación de Visual Studio bajo la carpeta:
Microsoft Visual Studio 9.0\Common7\IDE\Microsoft.Data.ConnectionUI.Dialog.dll
Microsoft Visual Studio 9.0\Common7\IDE\Microsoft.Data.ConnectionUI.dll
(En este caso para VS2008, en VS2005 también está disponible en su lugar será 8.0 ;P)
Una vez añadidas las referencias necesitamos importarlas mediante:
using Microsoft.Data.ConnectionUI;
Y por último para utilizarlas en nuestro proyecto:
Microsoft.Data.ConnectionUI.DataConnectionDialog dialogo = new Microsoft.Data.ConnectionUI.DataConnectionDialog();
//Añado por defecto las conexiones estándar, podemos seleccionar o limitar el tipo de conexión que mostrará la ventana de conexión.
Microsoft.Data.ConnectionUI.DataSource.AddStandardDataSources(dialogo);
Microsoft.Data.ConnectionUI.DataConnectionDialog.Show(dialogo);
Si queremos obtener la cadena de conexión resultante de los datos introducidos en la ventana de conexión es tan simple cómo asignar a una cadena el resultado de:
dialogo.ConnectionString
Configurando el Firewall de Windows para SQL Server
El tema de hoy es facilón, pero seguro que a muchos y no quiero dar nombres les ha dado más de una vez un dolor de cabeza. Al grano.

Pinchamos en cambiar la configuración y veremos la siguiente ventana:
Ahora añadiremos las excepciones, para ello hacemos click en el TAB Excepciones.Pulsamos en el botón Agregar un puerto y en la venta rellenaremos los campos Nombre con el valorSQL Server y el campo Número de puerto con el valor 1433. En la opción de protocolo seleccionaremosTCP.
También podemos abrir un puerto que escuche al servicio SQL Server Browser. Puede que te preguntespara qué sirve este servicio, pues sirve para que nos podamos conectar a nuestra instancia de SQL Serversi esta no está escuchando en el puerto 1433.Para configurarlo volveremos a agregar un puerto tal y como hemos hecho antes. La descripción seráSQL Server Browser, en el puerto 1434 de tipo UDP.
Lo primero que tenemos que hacer es mostrar la ventana dónde configurar las exclusiones del firewall.Para ello, nos vamos a inicio, ejecutar y escribimos firewall.cpl, abrirá la siguiente ventana:

Pinchamos en cambiar la configuración y veremos la siguiente ventana:

Ahora añadiremos las excepciones, para ello hacemos click en el TAB Excepciones.Pulsamos en el botón Agregar un puerto y en la venta rellenaremos los campos Nombre con el valorSQL Server y el campo Número de puerto con el valor 1433. En la opción de protocolo seleccionaremosTCP.

También podemos abrir un puerto que escuche al servicio SQL Server Browser. Puede que te preguntespara qué sirve este servicio, pues sirve para que nos podamos conectar a nuestra instancia de SQL Serversi esta no está escuchando en el puerto 1433.Para configurarlo volveremos a agregar un puerto tal y como hemos hecho antes. La descripción seráSQL Server Browser, en el puerto 1434 de tipo UDP.

-Una alternativa a configurar una instancia con nombre para escuchar en un puerto fijo es crear una excepción en el firewall para el ejecutable de SQL Server, lo que nos permitirá conectar a él independientemente del puerto que tenga abiertopara escucha.
Ruta en mi equipo dónde se encuentra el ejecutable de SQL Server 2005
C:\Program Files\Microsoft SQL Server\MSSQL.1\MSSQL\Binn
SQL Server 2008
C:\Program Files\Microsoft SQL Server\MSSQL10.SQL2008\MSSQL\Binn
En ambos casos elegiremos el fichero ejecutable sqlservr.exe
Si queréis profundizar un poco más en la configuración del firewall para Analisys Services, ...os dejo los enlaces en los BOL, para SQL Server 2008:
2008 ==> ms-help://MS.SQLCC.v10/MS.SQLSVR.v10.es/s10sq_GetStart/html/f55c6a0e-b6bd-4803-b51a-f3a419803024.htm
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.
que nos da como resultado en mi caso la página (1:126)
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.......
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
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.
-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?
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
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)
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
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
--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
sábado, 20 de septiembre de 2008
Precios SQL Server 2008
En este enlace tenéis los precios de las distintas versiones de SQL Server 2008.
http://www.microsoft.com/sqlserver/2008/en/us/pricing.aspx
http://www.microsoft.com/sqlserver/2008/en/us/pricing.aspx
Suscribirse a:
Entradas (Atom)



