Not Enough: El Query Governor en SQL Server 2005

Hace tiempo publiqué un post dedicado a mis amigos los DBAs, pero desde entonces no he dedicado ningún articulo dedicado en exclusiva a tareas de administración en entornos SQL Server. Esta carencia de posts no se debe a una aversión ciega a los DBAs por mi parte; de echo, les tengo un respeto enorme. Yo no podría sentarme día a día a realizar operaciones críticas en un servidor y aguantar la presión (principalmente porque soy muy torpe y despistado, como mi amigo el pezuñas, y si el se equivoca de botón, yo también puedo hacerlo).


Hoy voy a tratar de redimirme, de aportar algo a la comunidad de DBAs en su continua batalla con los usuarios… hoy quería hablaros de una herramienta muy poco conocida dentro de SQL Server: el Query Governor (música de suspense aqui, por favor…), que no es más que un mecanismo de control de ejecución de consultas pesadas. ¿Para que nos sirve esto? Veamos pues…


Un Escenario…


Imaginemos un escenario como el siguiente: tenemos un entorno transaccional tradicional que es atacado por una aplicación. Tanto la aplicación como la base de datos están bien dimensionadas para el uso diario y rutinario. Sin embargo, un buen día se decide implementar funcionalidad de reporting sobre la misma base de datos, ya que no hay presupuesto/tiempo/conocimientos para implementar un sistema de reporting paralelo. Se puede dar el caso que ciertas peticiones de informes se realicen sin problemas, mientras que algunos informes concretos, debido a la pesadez de las consultas subyacentes, nos dejen temblando el servidor, afectándonos al rendimiento de la operativa principal del sistema.


Si nos encontramos con este escenario, una posible solución es notificar a todos los usuarios que retrasen la ejecución de estos informes para horas de baja actividad del sistema… *carcajadas* … Sabemos que esa no es una opción válida para un administrador; sabemos como son los usuarios, les conocemos bien 🙂


Una solución fantástica sería poder limitar el consumo de CPU y de memoria que puede emplea una consulta o grupo de consultas para su ejecución. ¡La buena noticia es que esa solución existe! La mala noticia es que no os voy a hablar de ella por ahora 😉 Se trata de mi característica favorita de SQL Server 2008, conocida como el Resource Governor, y os hablaré de ella en un post próximo.


No obstante, antes quería escribir este post, que se basa en una solución intermedia, que consiste en cancelar la ejecución de una consulta cuyo consumo de CPU exceda un umbral predefinido. Esta solución no es tan elegante como la anterior, pero la ventaja es que la tenemos disponible en SQL Server 2000 y SQL Server 2005, con lo que podemos aplicarla a entornos actuales de producción.


Ahora que tenemos claro un escenario de ejemplo y la herramienta que vamos a utilizar, podemos pasar a describir al…


Query Governor


Siempre que pienso en el Query Governor me viene a la mente el retrato del Gobernador de Barbados, e historias de piratas, corsarios y la buena vida en Port Royal vienen a mi mente… pero lamentablemente la realidad es mucho más aburrida 🙁


El Query Governor, como hemos venido comentando, nos permite definir un umbral de tiempo de ejecución para nuestras consultas. Esto es, si la estimación del tiempo que va a durar una consulta es superior al valor definido como limite de tiempo en el Query Governor, esta consulta no llegará a comenzar su ejecución.


Para ver el valor actual, lo que debemos hacer es consultar el valor de los parámetros de configuración. Podemos hacerlo mediante la interfaz de usuario del SQL Server Management Studio, o mejor aún, mediante el procedimiento almacenado sp_configure. Como se trata de una opción avanzada, antes de poder visualizarla debemos habilitar las opciones avanzadas de configuración:



sp_configure ‘show advanced options’, 1
GO
RECONFIGURE
GO
sp_configure


Esto nos debería devolver la lista con todos los parámetros de configuración, entre los que se encontrará el query governor cost limit, que en mi caso vale 0 (el valor por defecto, que quiere decir que el Query Governor no está en uso).


Si alteramos el valor, podemos establecer el número de segundos máximos que otorgamos a la ejecución de cualquier consulta sobre toda la instancia. Podemos también establecer este parámetro a nivel de conexión, con el parametro SET query_governor_cost_limit, pero siendo realista ¿que cliente se va a poner restricciones a si mismo? 🙂


Vamos a escribir una consulta de ejemplo que resulte bastante pesada, por ejemplo la siguiente:



CREATE DATABASE PruebaQueryGovernor
GO
USE PruebaQueryGovernor
GO

CREATE TABLE dbo.Numeros
(
   Numero INT IDENTITY(1,1) PRIMARY KEY CLUSTERED
)
GO

WHILE COALESCE(SCOPE_IDENTITY(), 0) <= 100000
BEGIN
   INSERT dbo.Numeros DEFAULT VALUES
END

SELECT * FROM dbo.Numeros


Como se puede apreciar en el código, nos limitamos a crear una tabla auxiliar de números (viva la numeración!), en éste caso los primeros 100.000 números. La construcción de esta tabla tarda poco mas de 6 minutos en mi portátil, y bajo la configuración por defecto se ejecuta sin ningún problema. Vamos ahora a establecer un valor de umbral de tiempo de ejecución de, por ejemplo, 100 segundos:



sp_configure ‘query governor cost limit’, 100
RECONFIGURE


Ahora, si eliminamos la base de datos de prueba y volvemos a crear al tabla y a intentar poblarla, veremos que no se llega a realizar ninguna inserción, pues SQL Server determina que la consulta es demasiado pesada y la cancela antes de su ejecución. Ain’t it fun? 🙂


Conclusiones


Hemos repasado el Query Governor al que tanto provecho le podemos sacar en nuestros despliegues actuales sobre SQL Server 2000 y SQL Server 2005, y de paso, he dejado caer un poquito de información acerca del Resource Governor de SQL Server 2008 para que la curiosidad os pueda… quiero creer que lo suficiente como para que todos juntos os estéis descargando como locos la última CTP de SQL Server 2008 para probar el Resource Governor, los servidores se colapsen, salga en los telediarios y en el programa de Ana Rosa y en el Sé lo que Hicisteis…. pero bueno, me conformaré con que al menos os despierte el interés suficiente como para leer el siguiente artículo 🙂


Rock Tip:

Como hemos visto en las conclusiones, el Query Governor de SQL Server 2005 es muy práctico, pero aún así it’s not enough. ‘Not Enough‘ es también el titulo de una balada/medio tiempo de Van Halen… bastante ñoña, todo hay que decirlo, pero no por ñoño, menos temazo… ojo… que en los Rock Tips del tio Doval solo aparecen temazos!.


En serio, si no la conocéis os recomiendo que le peguéis un orejazo; aunque no seas muy ‘rockeros’, este tema merece la pena 🙂

Against the Law: Beware the Natives

Voy a comenzar algunas entradas en el blog relativas a depuración de aplicaciones Win32, por lo que parece interesante sentar antes unas bases teóricas sobre arquitectura de memoria y procesos de Windows NT. Esto, por otra parte, es muy útil a la hora de planificar el despliegue y configuración de aplicaciones de servidor, como puede ser SQL Server, por lo que no solo recomiendo la lectura a los interesados en el desarrollo de software.


Me plantee escribir la introducción desde cero, pero me acordé que hace cosa de un año escribí un artículo similar para la revista de los clubes .NET, de modo que saltándome a la torera los derechos de autor (que para algo el artículo es mío XD) y manteniéndome fiel a mi principio de Supreme Laziness, he decidido hacer un copy&paste sin remordimientos.


Espero que os guste!


Beware the Natives!


Un vistazo a la arquitectura de memoria y procesos de Windows NT®


Los que me conocéis sabéis que siento verdadera pasión por la plataforma .NET, pasión compartida, supongo, con todos los que estáis leyendo esta revista. De hecho, mis últimos temas de conversación favoritos para esas tardes de cervezas con los colegas son el recolector de basura y los objetos lázaro, el namespace System.Transactions y las plantas rodadoras.


Sin embargo hoy me siento rebelde y provocador, y me gustaría que me acompañarais en una breve excursión. Imaginaos a vosotros mismos en un bote en un río (ejem, no seguiré por ahí, que no estamos para pagar derechos de autor a los de Liverpool). Partiremos de nuestro hábitat natural, el mundo administrado, la tierra de Heljsberg y Wiltamuth, para adentrarnos en las oscuras y desconocidas tierras nativas (nunca mejor dicho) de Cutler, el núcleo de Windows NT® (2000, 20003, XP).


Muchas veces tengo la impresión de que en nuestro entorno, entre los apasionados de .NET, existe una especie de corriente autárquica; parece que no queremos saber nada de ése mundo exterior. Parecemos creer que nos podemos olvidar de sistema operativo subyacente (ya sea Windows, GNU/Linux, etc…) y permanecer en nuestra burbuja administrada. Sin embargo, veo constantemente ejemplos en la vida real de problemas de rendimiento o fallos de aplicaciones que, o bien se derivan de un desconocimiento de lo que hay por debajo de la plataforma, o bien podrían ser detectados y depurados mucho más fácilmente de conocer estas nociones básicas. Por eso creo importante dedicar unas pocas palabras a sentar al menos un conocimiento básico sobre la arquitectura de los sistemas Windows NT®, y hoy me centrare principalmente su gestión de memoria y de procesos.


NOTA: Antes de comenzar, me gustaría aclarar que todo lo que os voy a comentar de aquí en adelante es cierto en entornos Windows de 32 bits, ya que en los 64 bits la historia cambia bastante.


Programas, Procesos, hilos, y la madre que los parió…


Como ya sabemos, las aplicaciones que ejecutamos en nuestra máquina se convierten en procesos. Aunque a primera vista parece que un proceso es lo mismo que un programa, esto no es del todo cierto; podríamos decir que un programa es una secuencia estática de instrucciones, y el proceso es una estructura dinámica, creada por el loader sistema operativo a la hora de cargar un programa en memoria para comenzar su ejecución.


Estos procesos contienen, entre otras cosas, un espacio de memoria virtual privado (del que hablaremos más adelante), el código y datos del ejecutable inicial, así como uno o más hilos de ejecución.


Estos hilos son los que el sistema operativo planifica para su ejecución; podríamos considerarlos como la unidad mínima de planificación. Así que ya sabéis, a partir de ahora si alguien os vuelve a decir que el sistema operativo está ejecutando un proceso, podéis aclararle que lo que se ejecutan son los diferentes hilos del proceso, y de paso seguro que os ganáis un Certificado de Súper Gafotas.


Os adjunto la salida generada por la herramienta gratuita PsList de SysInternals (www.sysinternals.com) sobre uno de los procesos de mi máquina (un notepad.exe en éste caso). Como podéis ver, el proceso está compuesto por cinco hilos de ejecución diferentes, de los cuales podemos ver su identificador (TID), su prioridad, número de cambios de contexto, estado y estadísticas de tiempo de ejecución.


psList


Como ya sabéis, Notepad.exe es una aplicación nativa; os propongo como ejercicio observar cómo se comporta un PsList sobre una aplicación administrada con múltiples hilos de ejecución usando System.Threading.


Espacio de Memoria Virtual


Ahí va una afirmación sorprendente: todos los procesos que se ejecutan en nuestras máquinas Windows disponen para 2 Gb de espacio de memoria virtual para ellos solitos, que se llama espacio de memoria virtual privado. Esto es así independientemente de que nuestra máquina tenga 128 Mb o 16 Gb de RAM, y es independiente de la cantidad de memoria que tengamos establecida en los archivos de paginación. Es más, si tenemos en nuestro sistema 10 procesos, entre todos tendremos un total de 20 Gb de espacio de memoria virtual privado.


Evidentemente toda magia tiene su explicación. No hay manera en la cual podamos tener persistidos en memoria datos que ocupen más que la cantidad total de memoria física disponible (RAM + Archivos de Paginación), por tanto el sistema operativo dispone de mecanismos que mapean las direcciones del espacio de memoria virtual con ubicaciones físicas de memoria, dándose la posibilidad de que la misma dirección de memoria dentro del espacio de direcciones virtual en dos procesos diferentes apunte a dos posiciones de memoria física diferentes.


Cada proceso, por tanto, tiene 2 Gb de memoria virtual donde ubicará sus recursos, que principalmente serán los siguientes:



  • Imagen del código de la aplicación

  • Imagen de todos los módulos (.dlls) empleados por la aplicación

  • Uno o más heaps

  • Una pila (stack) por cada hilo de ejecución (otra pila se crea automáticamente dentro del área de memoria destinada al Kernel, que comentaremos después)

  • En caso de ser una aplicación .NET, un heap adicional llamado Managed Heap, que es donde se realizan todas las reservas de memoria y por tanto, el ámbito donde opera el recolector de basura.

La figura que se muestra a continuación representa el espacio de memoria privado de una hipotética aplicación administrada compuesta de un ejecutable (demo1.exe), con dos librerías enlazadas (lib1.dll y lib2.dll), dos hilos de ejecución y un heap administrado.


VAS-Process


Este heap administrado se comporta de manera diferente si estamos en un entorno de servidor o en un Workstation. En el primer caso, el managed heap se compone de segmentos de 64 Mb, con un managed heap en cada procesador del sistema. En el caso de tratase de una estación de trabajo, se trata de segmentos de 16 Mb. ¿Cómo podemos determinar que versión del recolector de basura estamos empleando? Para ello solo debemos comprobar si estamos empleando la mscorwks.dll (Workstation) o la mscorsrv.dll (Servidor).


Como apreciamos en la figura, los diferentes hilos de un mismo proceso comparten el mismo espacio de memoria virtual privada, ya que sus diferentes pilas están en el mismo área de 2 Gb. De éste modo los diferentes hilos pueden acceder a la misma memoria. Esto no ocurre a la hora de comunicarse con otros procesos, para lo cual hay que emplear otros mecanismos de los que hablaremos en otra entrega de ésta serie.


A todo esto hay que sumarle un área inmutable (común para todos los procesos) de otros 2 Gb dentro del espacio de memoria virtual que almacena estructuras internas del sistema operativo, como las Page Table Entries, handles y demás. Es la zona de memoria para el Kernel, y se puede ver en la siguiente figura.


VAS-Overview


La figura sirve de sumario de la estructura de procesos y memoria en un entorno Windows en su configuración por defecto. Y digo en su configuración por defecto porque este balance “2 Gb para proceso de usuario / 2 Gb para Kernel” puede ser alterado mediante los siguientes parámetros suministrados al kernel en el fichero boot.ini:



  • /3GB:


Mediante este switch indicamos al sistema operativo que queremos asignar más memoria a las aplicaciones y menos al sistema operativo, de modo que el particionado se hará dejando 1 Gb para el Kernel y 3 Gb para el modo usuario.


Para que nuestras aplicaciones nativas puedan beneficiarse de éste incremento en su espacio de direcciones virtual, deberemos compilarlas con la opción /LargeAdressAware. En el caso de nuestras aplicaciones .NET, si bien el CLR respeta este flag, el compilador de C# no tiene opción para establecerlo, por lo que debemos editar la cabecera PE del ensamblado usando editbin:


“editbin /largeadressaware <myapp.exe>”



  • /UserVa = XXXX


Usando el switch /3Gb en conjunción con /UserVA=xxxx podemos hacer una ajuste fino de la cantidad de memoria que queremos asignar al proceso de usuario, estableciendo un valor en megas entre 2000 y 3000. Esta opción solo está disponible en Windows 2003 Server y Windows XP.


¿Y por qué me cuentas todo eso?


Un ejemplo sencillo, pero que me encanta exponer cuando comento estos temas, es un servidor de FTP. Cuando propongo el diseño de un servidor de FTP, la gente se suele sentir atraída por la idea de usar un hilo de escucha de peticiones, más otros n hilos, uno por cada cliente que se conecta al servidor de FTP. El hilo principal haría un spawn de un nuevo hilo de ejecución con cada conexión entrante, y cuando ésta conexión se cerrara, se haría lo propio con el hilo principal.


Suena bastante lógico, pero si pensamos un poco en ello, y a la vista de lo que hemos comentado antes, podemos ver que ésta solución no escala precisamente bien. El tamaño por defecto para cada pila es de 512 Kb, y considerando que necesitamos dos pilas por cada hilo, la aplicación consumiría 1 Mb por cada conexión solo para sus pilas.


¿Quiere esto decir que no debemos emplear múltiples hilos a la hora de diseñar nuestras aplicaciones? Evidentemente no es así, pero hay que tener un cuidado especial a la hora de diseñar nuestras aplicaciones multi-hilo para asegurarnos que escalen correctamente. Para mejorar la escalabilidad se recomienda emplear un Pool de hilos, como el ThreadPool de System.Threading o el QueueUserWorkItem de la API de Windows 2000, y que por cuestiones de espacio y ámbito no trataré en éste artículo.


En la práctica también podemos ver ejemplos de problemas de fragmentación de memoria (muy típicos en despliegues de IIS), bloqueos completos de un servidor por agotamiento de PTEs, y un largo etcétera de problemas que un conocimiento superficial del sistema operativo subyacente nos puede ayudar a detectar y tratar rápidamente.



Despedida


Hasta aquí hemos llegado en esta breve introducción a la arquitectura de procesos y memoria de los sistemas Windows NT®. En un futuro artículo exploraremos ese espacio entre el código administrado y el código nativo, chapotearemos en ese rio entre P/Invokes y Marhallings (y de paso, haremos nuestros pinitos con WinDbg) para comunicar una aplicación .NET con una aplicación Win32 existente. Si os resulta atractivo, ¡ya sabéis donde podréis encontrarlo!


Referencias Bibliográficas:


– Microsoft Windows Internals, 4th Ed. [ M. Russinovich / D. Solomon], Microsoft Press, ISBN: 0-7356-1917-4


Rock Tip:

En el caso de hoy, y debido a mi infracción flagrante de los derechos de autor de mi artículo en student.NET, he decidido hacer alusión no ya a una canción, sino a un disco; se trata de ‘Against the Law‘, de los heavys cristianos Stryper. Es una banda curiosa, famosos por la increible voz del guitarrista/vocalista Michael Sweet, por los peinados cardados que caracterizaban a estas bandas en los años 80 y, como no, por esas mallas y toreras amarillas y negras que se atrevían a lucir en sus conciertos!! Algún día conseguiré yo unas iguales! 🙂


Os voy a dejar una enlace a uno de sus temas más clásicos, ‘Calling on You‘. Yo adoro a este grupo, pero pinchad bajo vuestra propia responsabilidad 🙂

I Wonder: SQL Server 2005 Express SP2 Panic!!

El otro día llego a mi buzón de entrada un correo de un compañero con el subject «DNN Panic!». El correo hacia referencia, entre otras cosas, a un mensaje de advertencia que aparecía en el errorlog de un SQL Server 2005 Express que estaba sirviendo a un portal DotNetNuke. El mensaje en cuestión aparecía cada dos o tres minutos, y tenía el siguiente aspecto:



SQL Server has encountered 1 occurrence(s) of cachestore flush for the ‘Object Plans’ cachestore (part of plan cache) due to some database maintenance or reconfigure operations.


Como debería ser bien sabido por todos los que tenemos que trabajar con o contra un SQL Server, cuando se realizan ciertas operaciones en la base de datos se puede forzar una limpieza de la caché de planes de ejecución (similar a cuando se ejecuta un DBCC FREEPROCACHE, etc…). En principio, salvo casos muy puntuales, no es buena idea, porque al eliminarse la caché, todos los procedimientos almacenados se han de reconstruir; por tanto, las siguientes veces que se invoquen, se perderá cierto tiempo en la recompilación y almacenado de ese plan. Lo mismo es aplicable a las otras cachés que existen en SQL Server.


El mensaje de error que hemos visto es un nuevo mensaje introducido en el SP2, para intentar localizar que posible plan de mantenimiento o tarea esta haciendo limpiando la caché de los planes (o de otro tipo de cachés).


Las operaciones que pueden producir esta limpieza de planes son las siguientes:



  • Comprobación de consistencia mediante DBCC CHECKDB (Solo en SQL Server 2005 RTM o SP1.. en SP2 no se limpian por defecto)

  • Si la base de datos tiene habilitado el autoclose, cada vez que se hace un shutdown de la base de datos se limpia la caché.

  • Poner la base de datos online u offline

  • Poner la base de datos en modo readonly o writeonly

  • Cambiar el nombre de la base de datos, cambiar collation, etc…

  • Hacer un restore de la base de datos

  • Hacer un attach de la base de datos

  • Evidentmente, hacer un DBCC FREEPROCCACHE o un DBCC FREESYSTEMCACHE

En el caso que nos ocupaba (nuestro DNN Panic!! 😉 ) se daba el caso más común, es decir, que el autoclose de las bases de datos estaba habilitado. Este es el comportamiento por defecto en la versión Express de SQL Server, ya que facilita el despliegue y movimiento de los ficheros de datos. No obstante, cada vez que se hace un shutdown de la base de datos, se obliga a limpiar las cachés, lo que trae consigo dos consecuencias:



  1. Aparece el molesto mensaje en el errorlog cada vez que se hace un autoclose. Esto es inocuo, excepto porque ‘ensucia’ el log y luego se complica la tarea de buscar errores o avisos mas severos.

  2. Como se ha explicado, se refleja el que ha habido una limpieza de cachés, con el problema de rendimiento que puede suponer sobre la aplicación debido a la necesidad de creación de nuevo de los planes de ejecución y la población de otras cachés.

Conclusión:

Si tenéis alguna aplicación funcionando en SQL Server Express 2005, aplicad el SP2 y comprobad si os aparecen estos mensajes en el log. Si es así, comprobad si realmente es necesario que tengáis el autoclose establecido, y en caso de que no lo sea, estableced el autoclose a false para evitar perder las cachés.


Os ahorraréis mensajes que ensucian el log y de paso se deberían apreciar mejoras de rendimiento… no obstante, el rendimiento en un SQL Server es algo muy complejo, así que mejor lo dejamos para otra serie de artículos.


Rock Tip:

A este post le he adjudicado el temazo ‘I Wonder‘, de los hardrockeros suizos Gotthard. Muchas veces nos quedamos mirando a un mensaje de error o advertencia y no podemos evitar pensar ‘I Wonder… que narices querrá decirme esto…’ 🙂


Dudo mucho que los chicos de Gotthard hayan dedicado su tema a todas esas preguntas que nos hacemos cuando vemos un mensaje extraño en el log de SQL Server; aún así, para mi su ‘Lipservice’ fue uno de los mejores discos de 2005 y por tanto, aprovecho para recomendarlo a los más duros, pero con corazoncito, de la comunidad geek 😉

Leave the Storm Behind: Subiendome a un tren en marcha…

Hace mucho que no estoy presente en geeks.ms, muy a mi pesar. Los que me conocéis personalmente sabéis que he estado pasando una época un poco dura, pero lo importante es que la normalidad ha vuelto y espero que aquellos que os atreváis a leerme tengais mucho material mío de aquí en adelante.

Durante estos meses muchas cosas han pasado; geeks.ms no ha dejado de crecer a un ritmo espectacular, Visual Studio 2008 ha llegado, ya nadie se maravilla con LINQ, tenemos a tiro de piedra SQL Server 2008 (que para mi y para muchos siempre será Katmai), Windows Server 2008… si bien durante estos meses he seguido con la antena puesta y trabajando con todas las betas que pude obtener, no puedo evitar que ahora, en el momento de retomar este blog, sienta un poco ese vertigo del que Jorge nos hablaba hacia poco.

Tengo ya algunos artículos en mente; estos días seré bastante oportunista, y aprovecharé la cercanía de Katmai para hablar escribir sobre el que sin duda es uno de mis productos favoritos de los chicos de Redmond. También tengo algunos artículos pendiente, como cierta sesión de WinDbg + winmine.exe en tierras Gallegas, o una serie de artículos sobre depuración post-mortem básica.

Por último, me gustaría disculparme si hay algún comentario, duda o cuestión realizada en alguno de los posts anteriores que no he podido responder durante estos meses anteriores. Si es así, no dudes en replanteármelas en los posts apropiados o en enviarme un mensaje privado!

Rock Tip:

Siguiendo la costumbre que tenía en el blog, el titulo de cada articulo irá precedido del nombre de una canción que de algún modo tiene relación con el post actual. En este caso, y en lo que constituye un penoso ejercicio de SSP (Shameful Self Promotion xD) el tema elegido es ‘Leave the Storm Behind’ de Angel Divine.

¿Que quienes son Angel Divine? Pues bueno, eran mi grupo de juventud y años mozos, de ahí lo del SSP 😛 Aquel tema se compuso en una época mala del grupo, y representaba las ganas y el empuje para dejar los malos rollos atrás y tirar adelante con lo que nos gustaba. Es exactamente eso lo que siento estos días, y por ello no podía titular a este post de otro modo.

Bang Bang: Marcado!!

 

Yuhuuu!! Me ha tocado!! 🙂 Me han marcado David Salgado y Miguel Ángel Ramos, y aunque estos días estoy hasta arriba (cosa que se nota en lo abandonado que tengo el blog :() no he podido resistirme a responder y sobre todo, marcar a otros cinco elementos 😉

Pues ahí van mis cinco cosillas:

  1. pablo->getCompBeginning();

    Empecé en esto en el 85, cuando mis padres le compraron a mi hermano un Amstrad CPC464 😀 Mi hermano nació en el 77, yo en el 79, así que imaginaros a esos dos críos (junto con el crío más grande de todos, mi padre) aprendiendo con los manuales del ordenador y, sobre todo, aquellas impresionantes revistas de la época, como la espectacular Amstrad Semanal, donde hice mis primeros cursos de BASIC y ensamblador del Z80.

    Me pongo nostálgico cada vez que lo recuerdo ¡Pero que bien lo pasé con aquel bicho tan feo! Siempre me acordaré del ejemplo para dibujar un circulo en su BASIC: como no había primitiva como tal para hacer un circulo relleno (de aquella, para mí, era un redondel xD) el manual de instrucciones daba un ejemplo para realizarlo a base de tirar líneas desde el centro hasta los diferentes puntos que conformaban el borde. Como os imaginaréis, esta técnica tan tercermundista, junto con la bajísima resolución del mítico modo 0, hacía que el relleno fuera, cuanto menos, pintoresco 🙂 Eso sí, impagable la trigonometría que aprendí con el bicho…  

  2. pablo->getFavMusic();

    Adoro la música. No puedo decir que es mi pasión, porque para bien o para mal soy un hombre primario, con muchas, muchas pasiones 😀 Pero lo cierto es que la única cosa que pudo haberme apartado de la informática hubiera sido la música. Toco la guitarra, he tenido la suerte de dar muchos conciertos en mi vida y, aunque ese mundo es muy perro, nunca podré cerrar del todo esa puerta… aunque supongo que mi máxima meta ahora seria marcarme un tema con Don Box y Pat Helland xD

    ¿Estilos? Muchos, pero principalmente el hard rock de los ochenta y primeros noventa (Danger Danger, Warrant, Europe, Poison, Sangre Azul…). Eso sí, en el fondo escucho prácticamente de todo; creo que soy la única persona que ha logrado escuchar un disco de Craddle of Filth entero y acto seguido, cambiarlo por un recopilatorio de tangos xD

  3. pablo->getFunnyFact1();

    Me encanta todo lo que tenga que ver con la ciencia y tecnología, pero por encima de todo la aviación y la carrera (ejem.. he dicho carrera?!?!) espacial. Hay niños que soñaban de pequeños con ser bomberos y niños que soñaban con ser astronautas. Yo era de los segundos 🙂 Como eso va a estar muy difícil, con los años he rebajado mi sueño a poder sacarme una licencia de piloto civil y alquilar una avioneta de vez en cuando!

  4. pablo->getFunnyFact2();

    Cuando deje de estar de alquiler y pueda permitirme un sitio para vivir, no va a ser una casa, será un zoológico xD Me encantan casi todos los animales, pero en particular los perros. La notable excepción son los gatos; tanto egoísmo en un animal al que estás dando de comer todos los días me da un poco de cosa xD

  5. pablo->getFunnyFact3();

    A pesar de mi aspecto (vestimenta negra, botas camperas, greñufos…) me encantan las películas de animación y los peluches… (Esta no debería haberla dicho xD)

Bueno, ya sabéis algo más de mi… vamos a aprender ahora todos un poco más de…. de…. Cachero,  P4k0 Null, Fran Peula, Marco Amoedo y Augusto Ruiz.

Rock Tip:

Si habéis visto los otros posts de mi blog, siempre antecedo el nombre del post con el titulo de una canción que me parece que puede tener algo que ver. Siempre me ha apasionado compartir mis aficciones (en el fondo, todos estamos aqui por eso ¿no?) así que voy a extenderlo un poco más, poniendo en el pie de los posts un poquito sobre el tema.

Hoy le ha tocado el turno a «Bang Bang», un tema del primer disco de Danger Danger. Si os apetece oir una cancion happy, que anima al instante, probadla. Si os interesa la musica de guitarristas para guitarristas, principalmente instrumental, no os perdais los trabajos en solitario de su guitarrista, Andy Timmons, que para mi es el guitar hero con mas estilo que ha parido madre 🙂 

Bakk on Trakk: Gira Norteña del University Tour 2007

Anoche regresé a Asturias después de dos semanas guapas de mucha carretera y poca cama 🙂 Al curso en la La Coruña le siguió la gira norteña del UT 2007, en la que pude acompañar a Ethel, P4k0 Null, Cristian, Cachero y Eugenio en las universidades de Oviedo, La Coruña y Vigo (campus de Ourense).


La semana comenzó el martes en Oviedo, donde se nos unió Cachero para dar la sesión de Ajax. Tuvimos buena afluencia de asistentes, que además se mostraron muy participativos, como era de esperar en mi tierra 😉 Después de comer junto a algunos miembros del club .NET dimos nuestro primer asalto a la carretera, como no, en mi pony!

<Viaje en Coche: censurado>

… y así llegamos a La Coruña, donde nos reunimos con Marco, Susana y Eduardo para una cena muy agradable en un restaurante chino donde descubrí cosas tan interesantes como que las hormigas pueden constituir una peluca perfecta para un disfraz de Joaquín Luqui y que la salsa agridulce es, efectivamente, agridulce. Lo que no me quedó del todo claro es si es hierba o especia.

Al llegar al hotel descubrí que me había olvidado la fuente de alimentación del portátil en la Universidad de Oviedo, y peor aún, descubrí que no hay en el mercado aún ninguna fuente de alimentación genérica con el conector de mi portátil, con lo que mis esperanzas de poder trabajar algo esa noche y la siguiente desde el hotel se fueron al mismo sitio que las hormigas y la salsa agridulce unas horas más tarde.

El siguiente día estuvimos en La Coruña, con Eugenio a cargo de la presentación de Ajax. Fue genial poder charlar un poco con algunos de los chicos del curso de la semana pasada, y en general el evento estuvo bastante bien, salvo por un problema de timing con mi sesión (que poco me gusta ser el último XD). Al terminar las sesiones fuimos a comer, nos despedimos de Cristian y P4k0, Ethel y yo emprendimos camino a tierras Ourensanas como valientes (sobre todo ellos dos!).

<Viaje en Coche: censurado>

… y así fue como llegamos a Ourense. Pintoresco hotel, muy pintoresco. Nunca antes había visto una caja fuerte a pilas, ni una mesa para echar las cartas y leer el futuro en cada habitación, ni una planta destinada a las reuniones de una sociedad secreta dentro de un hotel! A parte de eso, las mantas olían raro, la habitación de Ethel parecía un congelador y las puertas de los ascensores recordaban preocupantemente a las compuertas de contención del Titanic. Yuyu.

A la vista de tal panorama, decidimos salir a la calle pensando que, con total seguridad, encontraríamos algo más acogedor donde cenar. Finalmente lo encontramos y pudimos disfrutar de una cena muy maja en un baruco muy acogedor. Eso sí, no sin antes vivir una experiencia traumática en un Centro Comercial que fácilmente podría haber sido empleado como escenario para una película ambientada en un escenario post-nuclear.

Y finalmente, ayer jueves repetimos el evento en Ourense, esta vez solos Ethel, P4k0 y un servidor. Sinceramente, he de quitarme el sombrero ante los aproximadamente 200 asistentes, que resultaron ser de los más participativos que me he encontrado en toda mi vida. Disfrute como un enano, y la sesión de XNA final decidimos darle conjuntamente P4k0 y yo cosa de media hora antes de su comienzo! Entre muchas de las anécdotas que me llevaré del mismo es que fue la primera vez que nos tiraron fotos en medio de una sesión! en definitiva, me quito el sombrero ante los chicos y chicas de la Universidad de Vigo, campus de Ourense. Habéis estado genial!

Gracias a todos por estos días tan fantásticos, especialmente a Ethel (por invitarme a la gira y fiarse de mis habilidades de chofer, y por ser tan maja, y por acercarnos un poco más a la obra de Shakespeare… XD), a Eugenio (por dedicarnos su tiempo para charlar de tecnología, la vida, el universo y todo lo demás justo el día antes de un examen! Suerte!), y como no, a Cristian, Cachero y P4k0; no os podéis imaginar lo orgulloso que me siento de tener unos amigos como vosotros… Keep Rockin’!

Monkey Business: Mono en un Virtual PC

Esta semana he estado en La Coruña dando un curso de Introducción a C# y la Plataforma .NET para algunos alumnos de la UDC y la verdad es que fue muy entretenido, me lo pasé como un enano y creo que los chicos también. A parte de la teoría de siempre sobre la plataforma y la sintaxis del lenguaje traté, como siempre, de dar un valor añadido; al fin y al cabo, limitarnos a leer las presentaciones y hacer cuatro demos me parece inútil en la mayoría de los casos. Mi audiencia de esta semana, por ejemplo, se encuentra inmersa en la temporada de exámenes parciales, por lo que muchos de ellos no podrán llegar a casa y ponerse a repetir lo que hicimos en el curso y profundizar en ello. Sin duda, toda la sintaxis y las demos que hayamos hecho se les olvidará, cosa que por otra parte me importa más bien poco, para algo tienen google, la MSDN y 32768 recursos adicionales en la red.

Lo que me interesa realmente es emocionarles, explicarles que puede hacer la tecnología por nosotros, que novedades aporta, y sobre todo, escenarios y casos de uso… en fin, que me pase el curso entero contando batallitas :_)  Estas batallitas, consejos desde las trincheras o como queráis llamarlo es lo que le da un valor añadido a una presentación o un curso. Los alumnos agradecen que nos pongamos en su entorno (como puede ayudarles .NET con su proyecto de Fin de Carrera, como se relacionan las clases de colecciones con lo que han estudiado en Estructuras de Datos, etc…) y que también les demos un pequeño avance de lo que podrán ver en las empresas en la vida real.

Con la tontería de las batallitas y del valor añadido, acabamos hablando y haciendo demos del recolector de basura, de los profilers (F1 y CLRProfiler principalmente), sandcastle, NUnit, FxCop y, como no, Mono. Así, hoy viernes compilamos bajo Mono algo de código que habíamos hecho el día anterior en Visual Studio .NET, y lo hicimos todo dentro de una máquina virtual con Monoppix en un Virtual PC.

Para quienes no lo conozcáis, Monoppix es un distribución Live CD de Linux (¡quizá deba decir GNU/Linux para que Kilian y sus acólitos me perdonen la vida! XD) basada en la popular Knoppix, lo que quiere decir que no necesitamos instalarla en nuestro disco duro, ya que se distribuye como un CD auto-arranque el cual, tras su carga, descomprime en memoria sus contenidos para poder usarlo como si estuviera desplegado en nuestro disco duro. La imagen de CD ocupa menos de 500 Mb y podéis descargarla libremente de internet (www.monoppix.com).

Como el uso de Mono en este taller iba a ser mínimo, y no me agradaba la idea de andar reiniciando para pasar de Mono a Vista, decidí probar a ver qué tal iba en una máquina virtual con Virtual PC. Para ello seguí los siguientes pasos:

  • Creé una máquina nueva con la siguiente configuración:
    • 512 Mb de Ram
    • Sin disco duro (inicialmente, luego podemos crear uno chiquito para el archivo de swap)
  • Agregué como unidad de CD la imagen .iso del CD de monoppix.

Arranqué la máquina virtual, y en pocos segundos la consola me saludo con el clásico «boot:». No tenía pensado pasarle ninguna opción al kernel, así que pulse enter y al minuto escaso tenía delante un escritorio KDE (mmm… molaba más con Gnome (1)) totalmente funcional, con Mono integrado y las herramientas básicas instaladas, como MonoDevelop (que aún así no pude aprovechar mucho, pues la interfaz de usuario se ve francamente mal en mi VPC). Grabé el estado de la máquina virtual después de la configuración básica del Knoppix y… Ta-Dah!!! Ya tenía mi máquina virtual con Mono en unos 500Mb, que pienso dejar por el disco duro del portátil para tener a mano; seguro que será muy socorrida para las típicas preguntas de los hijos de Stallman en más de una charla 🙂

En fin, el juguete está muy bien si queréis jugar y conocer lo que hay al otro lado del infierno 🙂 Es súper fácil montarlo como máquina virtual, ocupa muy poco, y para alguna demo está muy apañado. Just my ((double)2 / (double)100) cents.

 (1): Oh!! Dios!!! ¿Realmente he dicho eso? Primero Mono, después Gnome… ¿Acabaré poniendo un altar a Miguel de Icaza en mi casa y rindiéndole culto todas las noches? Brrrrrrr… escalofríos me dan, oye…

Paranoid: Cifrado de Datos en SQL Server 2005

Los DBAs son criaturas paranoicas. No, en serio, los amo de corazón, pero son la cosa más desconfiada que hay en el mundo; y si no lo es el DBA, lo será su jefe, o el jefe de su jefe, o alguien en su línea de reporte directo que considera que la seguridad de su empresa (ya sea ésta un Banco internacional o la Agrupación de Tamborileros y Triangulistas Amateur de Cerecinos de Campo) es crítica y de mayor importancia. Qué curioso, sobre todo si tenemos en cuenta su reticencia innata para actualizar de nivel de Service Pack, o para tener una cuidadosa política de permisos en el servidor que minimicen los riesgos de los ataques de inyección SQL, que no nos engañemos, si bien la vulnerabilidad de una inyección SQL la pone en bandeja el desarrollador, su explotabilidad viene determinada por la configuración y administración de la misma. Aquí estamos todos en el mismo barco, o como diría el gran Fran Peula, «Aquí, o f******* todos o la p*** al rio» :)).

Hoy he tenido un momento flashback. Como algunos de vosotros sabéis, hasta hace poco trabajaba en Microsoft dando soporte a SQL Server, y hoy me he acordado de dos clientes en particular. Uno de ellos, un chico gallego muy majo, de una empresa de desarrollo de La Coruña, que llamo a soporte de Microsoft porque habían sufrido una corrupción en uno de sus archivos de datos y era un tema crítico para ellos. La verdad es que trabajamos muy bien en ese caso; esfuerzos por los dos lados, nos quedamos bastante más tarde del horario establecido, y además hubo mucha suerte porque se pudo recuperar lo que necesitaban. Al final de la llamada, tras la recuperación de los datos, pude oír como pocas veces risas de satisfacción de éste chico y sus compañeros, se les notaba el tremendo alivio en todas las palabras de agradecimiento (realmente esa parte del trabajo era impagable… :_) ) y ¡¡¡hasta su compañero ‘linuxero’ alabó el producto y la calidad del soporte!!! ¿Creéis que me he acordado de él por todo esto? Pues no, me acordé de él porque tenía hambre, estoy en La Coruña y me prometió una mariscada xDDD Realmente no es el momento, porque no tengo casi nada de tiempo libre, pero la próxima vez que venga le llamaré; yo pondré las cervezas.

El otro cliente si tiene que ver con la parrafada inicial. Se trata de un chico de UK, un tal Greg, que estaba planeando el despliegue de una nueva aplicación, destinada a ser usada con SQL Server 2005, y que iba a contener información muy sensible. Lo que éste chico me preguntaba era básicamente si se podían cifrar los datos de una columna de SQL Server de tal modo que solo un usuario especial pudiera acceder a ellos, impidiendo el acceso a todos los demás usuarios, incluidos los sysadmin. Lo recordaré siempre porque fue mi primer caso con SQL Server 2005… ¿Veis? En el fondo soy un romanticón 🙂

Como me parece un tema interesante me gustaría compartir con vosotros una versión light del resumen que le hice, que a su vez estaba basada en dos geniales artículos de la MSDN, ya que estoy seguro que muchos de vosotros lo encontrareis útil tanto a nivel de desarrollo como de consultoría, etc. 

Cifrado de Datos en SQL Server Dosmilcinc… Yukon

Como suele suceder, escoger el nivel de protección adecuado consiste en buscar el balance entre la seguridad y la usabilidad (en el sentido de lo que se complique el empleo y administración de la base de datos). Para tomar esta decisión, primeramente debemos determinar de quien queremos proteger nuestros datos. Para ello vamos a considerar tres niveles de protección básicos:

  • Nivel 2: Protección frente a atacantes que pueden acceder a los ficheros físicos de la base de datos.
  • Nivel 1: Nivel 2 + protección frente al Sysadmin
  • Nivel 0: Nivel 1 + protección frente al propietario de la base de datos (dbo)

Ahora voy a proceder a explicar la aproximación que deberíamos tomar para securizar nuestros datos sensibles en cada uno de esos niveles, desde el más seguro (Nivel 0) hasta el menos seguro, pero más usable (Nivel 2).

Todos estos niveles se basan en el hecho de que los datos sean protegidos por una clave simétrica, ya que es la manera más eficiente de cifrar los datos, pero emplean diferentes mecanismos para proteger ésta clave simétrica. A partir de aquí surgen las diferencias:

            Nivel 0: Solo el usuario autorizado puede ver sus datos

Para lograr este grado de protección de nuestros datos, la clave simétrica debe ser protegida por una clave que solo será conocida por el usuario que ha cifrado los datos. Éste es el modo más seguro, ya que no hay manera en la cual el propietario de la base de datos, o el sysadmin, puedan acceder a la clave simétrica, ya que ésta no está almacenada en el servidor.

Los ficheros de datos se aseguran de este modo también, ya que aún en el supuesto de que un atacante consiga obtener acceso a los ficheros y adjuntarlos a su servidor, no podrá acceder a las columnas cifradas mientras no tenga a su disposición la contraseña de cifrado de la clave simétrica.

Evidentemente, hay una seria contrapartida en términos de usabilidad: para acceder a estos datos, necesitamos asegurarnos de que la clave sea abierta, y para ello debemos suministrar explícitamente la clave con la que se cifró la clave simétrica.

Podemos comprobar en cualquier momento las claves abiertas en una sesión dada simplemente echándole un vistazo a la vista de administración del sistema sys.open_keys. Si la clave no estuviera abierta, entonces la siguiente sentencia DDL sería necesaria para abrirla:

OPEN SYMMETRIC KEY <nombre_clave> DECRYPTION BY PASSWORD = ‘<contraseña>’

            Nivel 1: Otorgándole acceso al DBO

En éste escenario suponemos que el propietario de la base de datos es de fiar y puede tener acceso a las columnas sensibles, de modo que nos podemos permitir relajar un poco las restricciones de seguridad; lo que haremos en este caso es proteger la clave simétrica con un certificado (o una clave asimétrica). La clave privada del certificado (o de la clave asimétrica) necesita ser protegida por la Database Master Key o llave maestra de la base de datos. Para lograr esto en el momento de creación del certificado, debemos simplemente omitir la opción ENCRYPTION BY PASSWORD:

CREATE CERTIFICATE cert WITH SUBJECT = ‘EncryptionCert’

Si ya disponemos de un certificado existente (o clave asimétrica) protegido por una contraseña, y queremos que la protección la realice la Database Master Key, deberemos alterar éste certificado. Me gustaría recalcar aquí que la sintaxis para esta labor puede parecer muy poco intuitiva, así que como siempre, en caso de duda deberemos recurrir a los Books On Line del producto.

ALTER CERTIFICATE cert WITH PRIVATE KEY DECRYPTION BY PASSWORD = ‘<password>’

Y aquí viene la parte importante, el momento donde realmente protegemos los datos del sysadmin. El usuario dbo, o el usuario con privilegios, debe asegurarse de que la Database Master Key esté protegida solo mediante una contraseña. En el momento de creación de ésta Database Master Key se establece que, por defecto, sea cifrada por la Service Master Key, de modo que debemos eliminar ésta protección con una sentencia DROP como la siguiente:

ALTER MASTER KEY DROP ENCRYPTION BY SERVICE MASTER KEY

De éste modo, el propietario de la base de datos tiene acceso a los datos del usuario privilegiado, ya que puede usar la Database Master Key para descifrar la clave privada en el certificado, de modo que pueda ser luego usada para abrir la clave simétrica y descifrar los datos protegidos. No obstante, estamos protegidos del sysadmin ya que no será capaz de abrir la Database Master Key sin la clave apropiada.

            Nivel 2: Otorgándole al Sysadmin acceso a los datos

En éste escenario vamos a confiar también en el usuario sysadmin; solo nos preocupa la posibilidad de que nuestros datos sean robados y queremos prevenir que los atacantes puedan acceder a los datos sensibles en caso de que se hagan con el fichero de datos y puedan adjuntarlo a su base de datos. 

Debemos cifrar los datos con una clave simétrica, y proteger ésta clave simétrica con un certificado (o clave asimétrica) tal y como vimos en el nivel 1 de protección. Éste ultimo certificado es protegido, como demostramos antes, por la Database Master Key.

La diferencia importante es que el propietario de la base de datos NO debería hacer un drop del cifrado de la Database Master Key por la Service Master Key. Es decir, debemos dejarlo tal como se crea por defecto, o bien, en caso de que haya sido modificado, volver a establecerla con la siguiente sentencia DDL:

ALTER MASTER KEY ADD ENCRYPTION BY SERVICE MASTER KEY

El sysadmin, de éste modo, tendrá acceso a la Database Master Key y por tanto, a cualquier objeto cifrado por la misma. Esto, evidentemente, implica que los datos no están protegidos ni frente al propietario de la base de datos ni frente al administrador del sistema, pero hemos conseguido que los datos estén protegidos en el fichero de datos. De este modo, si alguien robara los ficheros de la base de datos y fuera capaz de adjuntarlos a su propio SQL Server, no sería capaz de leer los datos cifrados ya que no tiene acceso a la contraseña que cifra la clave simétrica, ni acceso a ninguna de las claves de la jerarquía que protege la clave simétrica.

En resumen, el empleo de la jerarquía de claves en SQL Server 2005 facilita las áreas administrativas y de programación ya que no necesitamos abrir explícitamente las claves usadas para proteger los datos. No obstante, si queremos una securización adicional de los datos, debemos escoger la altura en la jerarquía a partir de la cual queremos cifrar la clave con una clave simétrica. Esto nos permite aumentar dramáticamente la seguridad, a costa, como ya vengo comentandoos, de una mayor complejidad administrativa debido al hecho de tener que abrir y cerrar las claves manualmente.

Desde un punto de vista del rendimiento, es evidente que se producirá una sobrecarga en el sistema. No obstante, no podemos estimarla a priori, ya que depende inmensamente del algoritmo de cifrado empleado, así como de la cantidad de los datos.

Ejemplo

Os dejo aquí un ejemplillo que muestra algunos de los conceptos que os comenté en el breve artículo. Es un script SQL para ir ejecutando pasito a pasito, leyendo los comentarios. Espero que el cacharro este lo formatee medio bien.

CREATE DATABASE PruebaBaseDatosSegura

GO

USE PruebaBaseDatosSegura

— Creamos una nueva tabla donde vamos a almacenar el nombre del empleado (no
— cifrado) y el numero de la seguridad social del mismo. Vamos a cifrar el número de
— la seguridad social durante la inserción, de modo que tenemos que tener esto en
— mente cuando establezcamos el tipo de datos, que deberá ser un varbinary de
— modo que pueda contener la cadena resultante por el algoritmo de cifrado.

CREATE TABLE empleados (emp_nombre varchar(50), nss varbinary(256) primary key clustered)

— Ahora creamos la clave simétrica que vamos a usar para cifrar/descifrar los datos

CREATE SYMMETRIC KEY skey WITH ALGORITHM = triple_des ENCRYPTION BY PASSWORD = ‘C1av3’

— Ahora un fragmento interesante… debemos tener en mente que si queremos usar
— una clave, debemos abrirla primero. Para abrir una clave debemos usar la sentencia
— OPEN. La clave podría estar protegida por un certificado, por la “Service Master Key”,
— por la “Database Master Key” o por una contraseña. En éste ejemplo, y para hacerlo
— coincidir con el escenario en el cual queremos evitar que el propietario de la base de
— datos y el sysadmin puedan acceder a los datos, debemos suministrar la contraseña
— en la sentencia open.

OPEN SYMMETRIC KEY skey DECRYPTION BY PASSWORD = ‘C1av3’

— Vamos a insertar ahora algunos valores, usando la función encryptbykey() para generar
— un stream cifrado de la cadena que le pasamos como parámetro.

INSERT INTO empleados values (‘Tom’, encryptbykey(key_guid(‘skey’), ‘111-11-1111’))
INSERT INTO empleados values (‘John’, encryptbykey(key_guid(‘skey’), ‘222-22-2222’))
INSERT INTO empleados values (‘Bob’, encryptbykey(key_guid(‘skey’), ‘333-33-3333’))

— Si ahora hacemos la select, podemos ver que el campo nss contiene solo un stream de
— bytes ilegible.

SELECT * FROM empleados

— Para poder leer los datos, necesitamos convertir desde el varbinary donde almacenamos
— los datos, al tipo de datos de destino deseado, en este caso, varchar.

SELECT CONVERT(varchar(256), decryptbykey(nss)) FROM empleados

— En el SSMS, usamos Ctrl-L o desde el menu: QueryDisplay Estimated Execution Plan,
— para comprobar el plan de ejecución estimado. Podemos ver que se realiza un descifrado
— por cada fila escaneada.

SELECT CONVERT(varchar(256), decryptbykey(nss)) FROM empleados WHERE CONVERT(varchar(256), decryptbykey(ssn) ) = ‘111-11-1111’

— … a ver que pasa con la clave cerrada…

CLOSE SYMMETRIC KEY skey
GO
SELECT CONVERT(varchar(256), decryptbykey(nss)) FROM empleados

— Limpieza final… Ahora borramos la base de datos de ejemplo

USE Master
DROP DATABASE PruebaBaseDatosSegura

Como se puede ver en el ejemplo, cada vez que queremos acceder a un campo cifrado debemos descifrarlo con una función, y después hacer un cast al tipo de datos deseado. Esto tiene un impacto sobre el rendimiento de la aplicación, pero es algo que deberíamos medir y probar en nuestros sistemas.

Respecto a los aspectos de seguridad, obviamente esta implementación es mucho más robusta de lo que nunca haya sido SQL Server 2000, pero eso no quiere decir que podamos descansar tranquilos simplemente por utilizar las características criptográficas del producto. Hay otros modos de atacar los datos; por ejemplo, si el administrador de la base de datos quisiera acceder a los mismos de modo no autorizado y fuera suficientemente hábil, podría recurrir a múltiples trucos para obtener los datos; desde sniffers para capturar contraseñas a ataques de fuerza bruta, pasando por el empleo malintencionado de un depurador sobre el producto.

Con esto quiero haceros consciente de que la seguridad no es solo un asunto de cómo almacenemos los datos; todos los detalles del entorno juegan su papel. Desde la configuración de permisos de Windows, al almacenamiento físico de los datos, todo ha de ser tenido en cuenta.

Ya terminoooo…

Me gustaría terminar con una reflexión que le hacía a Greg cuando estaba decidiendo su implementación final: a simple vista parece que la opción de cifrar con una clave que no se almacene en el SQL Server y solo conozca una persona parece la más segura, pero como un día el propietario de esta clave sea atropellado por el camión de los pollos(tm), abducido por los Vogones, o se vaya a cenar al Restaurante del Fin del Mundo nos podemos olvidar de todos los datos que estuvieran cifrados con su clave. Así de crudo.

Speed of Light: ¿Usa el DataReader cursores?

Hace unos días tuve una agradable conversación con unos compañeros que nos acabó llevando al espinoso asunto del uso de los cursores… momento en el cual este tipo de conversaciones suelen dejar de ser tan agradables y pasan a la categoría de Guerras de Religión (ya sabéis, cursores siempre vs. cursores nunca, vi vs. emacs, Windows vs. GNU/Linux y como no, el rey de las guerras de religión… Aritos de Cebolla vs. Fingers de Mozarella).


El caso es que yo, habiendo entrado en modo talibán durante el ejercicio de mis labores como detractor del empleo de los cursores, estaba defendiendo que no era la mejor de las ideas utilizar cursores para un proceso que podría trabajar potencialmente con millones de filas. Me quedé sorprendido cuando otro chico me comentó que los DataReaders de .NET estaban implementados mediante cursores, y ciertamente recordaba haber leído algo similar durante mi formación en ADO.NET, por lo que volví a la documentación de la MSDN y pudimos comprobar cómo los DataReaders funcionan mediante cursores forward-only, read-only.


Antes de que hubiéramos terminado de leerlo ya teníamos a Unai picando un código de demo :_) Cuando la terminó, la ejecutamos y monitorizamos su ejecución mediante el SQL Profiler (capturando eventos de cursores de servidor y de cliente… aunque los de servidor no debería aparecer nunca con ADO.NET, pero por si las moscas ;)), el performance monitor de windows (perfmon.exe) y las vistas de administración dinámicas de SQL Server 2005, y no pudimos apreciar la creación de un solo cursor.


Por una parte fue un alivio (nos parecía overkill que se crearan cursores con todos los DataReaders), pero por otra parte resultó bastante desconcertante el hecho de que en la documentación se hiciera referencia al empleo de cursores, pero en lo práctica no hubiera rastro de ellos. Tras unos minutos de investigación y el comodín de la llamada (gracias Nacho!!) descubrimos que los cursores forward-only, read-only en ADO.NET son los firehose cursors de ADO, que para empezar no son cursores, y por otra parte tampoco apagan fuegos! xD


En realidad, estos ‘cursores’ son solo un mecanismo para mover de modo rápido datos de un servidor SQL Server al cliente que los ha solicitado. En la práctica, lo que hacen es enviar directamente los datos solicitados por cliente al output buffer del SQL Server. Cuando éste buffer se llena, espera hasta que el cliente pueda recoger estos datos y lo vuelve a llenar de nuevo. Este proceso se repite una y otra vez hasta que el cliente puede recuperar todos los datos.


Como se puede ver, no es el cliente el que va solicitando items como en un cursor tradicional, sino el servidor quien envía todo lo que puede la output buffer. Los bloqueos solo se mantienen mientras el servidor mueve los datos a éste buffer, de modo que no depende de la velocidad de recogida de los datos por parte del cliente, lo que ayuda a mejorar considerablemente el rendimiento y concurrencia. 


En definitiva:



  1. Cuando veamos en la documentación de ADO.NET un cursor forward-only  read-only, no nos llevemos las manos a la cabeza. No son cursores de verdad, y su rendimiento y bloqueos no tienen nada que ver con un cursor ad hoc.

  2. Lo importante no es saber, es tener el teléfono del que sabe xD 

  3. Los aritos de cebolla molan 1024, pero los fingers de queso tiene un mayor Cool Factor(tm).

Remember Yesterday: Java y .NET pueden ser amigos…

Hoy estuve buscando por unas slides que había preparado hace mucho tiempo (de 2003, la primera charla que impartí sobre .NET en mi escuela, la EUITIO) y al volver a verlas, me encontré con una imagen de la que ya me había olvidado. Me hizo mucha gracia, y pensé en compartirla con vosotros:

Starsky & Hutch

¿No es encantadora esta estampa de amistad y buen rollito? 🙂 Mi hermano hizo la magia del photoshop (kudos pa él!!), pero lamentablemente no recuerdo quien me paso la foto original de S & H, pero realmente se merece que le ponga un altar en mi casa y le rinda culto todas las noches antes de irme a dormir! 

Por cierto, y rememorando aquella primera charla mía, un consejo: Cuando estéis dando una charla de introducción a .NET, ¡no expliquéis el algoritmo de recolección de basura! XD