Teoría BBDD

¿Es PLE un buen indicador de rendimiento de SQL Server?

Durante años, el Page Life Expectancy (PLE) ha sido una de esas métricas que aparecen en los scripts de monitorización como si fueran mantras sagrados. Una de esas columnas que se miran con recelo, que hacen saltar alertas y que, para algunos, justifican peticiones de más memoria RAM con la ligereza con la que se pide café. Pero como todo en SQL Server, nada es tan sencillo como parece y el PLE, aunque útil, tiene trampa.

¿Qué demonios es el PLE?

El PLE representa cuántos segundos, de media, una página de datos puede permanecer en el buffer pool antes de ser desalojada. Es decir, mide cuánto tiempo vive la información en memoria antes de que SQL Server tenga que expulsarla para hacer sitio a otra. Técnicamente, es un contador de rendimiento (sys.dm_os_performance_counters) que se encuentra dentro de Buffer Manager.

Cuando este valor es alto, respiramos tranquilos: significa que las páginas permanecen en memoria lo suficiente, probablemente porque tenemos un buffer pool holgado y un acceso a disco relajado. Cuando cae en picado, suele ser síntoma de presión de memoria o de lecturas físicas excesivas, muchas veces provocadas por planes de ejecución poco afortunados.

Ahora bien, el número mágico de 300 segundos (5 minutos) que algunos siguen usando como umbral es tan fiable como usar una brújula en mitad de un campo magnético. Ese valor tenía sentido… cuando los servidores venían con 4 GB de RAM. Hoy, con instancias que superan los 512 GB, seguir usando el mismo umbral es como usar una regla de colegio para medir una autopista.

Valores PLE deseables: ¿hay alguno?

Aquí viene la gran pregunta que a su vez es el gran problema del PLE: su valor es absolutamente relativo. Depende del tamaño del buffer pool, del patrón de carga de trabajo, de los tipos de queries que se estén ejecutando, y de si el sistema ha tenido un pico puntual de actividad.

Una instancia con 256 GB de RAM debería tener un PLE mucho más alto que una con 16 GB. ¿Cuánto más? No hay una cifra mágica, pero una orientación razonable sería multiplicar los segundos base (300 en los viejos tiempos) por un factor en relación al tamaño del buffer pool. O mejor aún, establecer una línea base propia de nuestra carga habitual y monitorizar desviaciones.

Porque eso es lo que importa: no tanto si el PLE es 2.000 o 20.000, sino si ha caído bruscamente respecto a lo normal. Un descenso repentino suele estar vinculado a algo que no encaja: una query que hace lecturas absurdas, un mantenimiento mal planteado, o simplemente un usuario que ha decidido escanear toda la tabla de movimientos de 200 millones de registros “por si acaso”.

El PLE no es una medida mágica

Muchos lo tratan como si fuera el santo grial de la salud del servidor, pero en realidad el PLE no mide nada en términos de experiencia de usuario. Es un indicador indirecto de presión de memoria, no una medida de rendimiento ni de latencia. Puede estar alto mientras el sistema responde lento, o estar bajo y aun así tener una experiencia fluida si las queries están bien cacheadas.

Además, el PLE es un promedio a nivel de NUMA node, lo que significa que puede estar sesgado si tenemos un servidor con múltiples nodos y la presión se concentra solo en uno de ellos. SQL Server calcula un PLE por cada nodo NUMA, pero los scripts que aglutinan el valor total no siempre lo desglosan correctamente. De ahí que convenga analizarlo por nodo para tener una visión clara.

Y por si fuera poco, el PLE se resetea con cada reinicio de la instancia. Así que no, si ves un valor bajo justo después de un restart, no es el fin del mundo: es simplemente lo que hay.

Detractores: con razón, no por moda

Los que critican el PLE no lo hacen por capricho. Lo hacen porque, en muchos entornos, mirar el PLE sin contexto lleva a diagnósticos erróneos y decisiones equivocadas. Se han visto DBAs pidiendo 128 GB de RAM más “porque el PLE está bajo”, sin pararse a mirar que el problema era una consulta sin WHERE que se colaba a producción cada viernes a las 15:00.

El PLE tampoco distingue entre lecturas necesarias y lecturas absurdas. Si haces un SELECT * de una tabla de logs históricos porque alguien quiere exportarla a Excel “por si acaso”, el PLE caerá en picado igual que si tuvieras una mala estrategia de índices. Así que usarlo como medida absoluta de salud es, como poco, ingenuo.

Alternativas: mirar más allá del PLE

Si queremos una visión más rica, hay vida más allá del PLE. Podemos observar métricas como el Buffer Cache Hit Ratio, aunque también con cautela, porque este valor suele estar cerca del 100% en casi todas las instancias modernas y no siempre significa lo que creemos. Lo que realmente nos interesa es entender qué queries están provocando lecturas físicas excesivas.

Aquí entra en juego la DMV sys.dm_exec_query_stats, que combinado con sys.dm_exec_sql_text y sys.dm_exec_query_plan, nos puede dar visibilidad sobre qué consultas están provocando lecturas físicas o lógicas desproporcionadas. También podemos revisar el sys.dm_io_virtual_file_stats para analizar el I/O por base de datos y archivo. 

Y si lo que nos interesa es el uso de memoria, el sys.dm_os_memory_clerks y el sys.dm_os_buffer_descriptors ofrecen información mucho más granular sobre cómo SQL Server está usando realmente la RAM.

Además, a partir de SQL server 2025 tendremos la nueva DMV sys.dm_os_memory_health_history pero eso da para otro artículo.

En resumen: el PLE puede servirnos como un primer vistazo, como ese canario en la mina que nos avisa de que algo pasa. Pero confiar ciegamente en él es como juzgar un libro por el grosor del lomo.

Monitorizar el PLE: ¿sí o no?

Entonces, ¿monitorizamos el PLE o no? Esta es una de esas preguntas que genera debates infinitos y respuestas del tipo “depende”. Yo voy a ser neutral, no voy a entrar en la trinchera de los que lo consideran inútil ni en la de los que lo elevan al nivel de oráculo. Lo que sí diré es que monitorizar el PLE puede tener sentido si sabemos lo que estamos mirando y no nos dejamos llevar por interpretaciones simplistas.

Si tenemos una línea base sólida, si entendemos la arquitectura NUMA de nuestra instancia y si usamos el PLE como un indicador más dentro de un conjunto más amplio de métricas, entonces puede ser útil. Pero si lo usamos como termómetro único del rendimiento, vamos a acabar medicando al paciente por fiebre sin saber que tiene apendicitis.

Conclusión

El Page Life Expectancy no está muerto, pero tampoco es un mesías. Es una métrica con contexto, con historia y con limitaciones. Sirve para levantar sospechas, no para dictar sentencias. Hay que leerlo con ojo clínico, entender lo que implica y, sobre todo, combinarlo con otras métricas más modernas y más específicas.

Como siempre, no hay atajos. Lo que hay es análisis, observación y un poco de sentido común. Que no es mucho pedir… salvo que creas que SELECT * sigue siendo buena idea.

Si tenéis alguna duda o sugerencia, podéis dejarla en Twitter, por mail o dejarnos un mensaje en los comentarios. Y recuerda que también tenemos un grupo de Telegram y un canal de YouTube a los que te puede unir. ¡Hasta la próxima!

Publicado por Roberto Carrancio en Cloud, Rendimiento, SQL Server, 0 comentarios

CPU NUMA: Cuando el procesador también tiene barrios

Hay palabras que, al oírlas, nos ponen en guardia. “NUMA” es una de ellas. No porque suene peligrosa, sino porque suele venir envuelta en conceptos vagos y soluciones mágicas a problemas que no entendemos del todo. Pero no nos engañemos: si administramos SQL Server sobre hardware serio (y no sobre portátiles reciclados con Docker “porque mola”), entender cómo se comporta la arquitectura NUMA no es opcional. Es imprescindible.

¿Qué es NUMA? Una ciudad con barrios.

NUMA (Non-Uniform Memory Access) es una arquitectura de memoria en la que cada CPU (o grupo de CPUs) tiene acceso preferente a un bloque de memoria. A este conjunto se le llama nodo NUMA. Sí, se puede acceder a la memoria de otros nodos, pero es más lento. Y en un mundo donde las latencias de microsegundos importan más que los deadlines de los Project Managers, eso no es un detalle menor.

Puede parecer lioso pero vamos a verlo en una imagen para que no haya dudas. Realmente todo esto no es algo abstracto, viene directamente definido a nivel hardware. Las placas base de los servidores tienen varios socket de procesadores y, cada uno de ellos, tiene unos slots de RAM más cercanos a los que accede con menor latencia.

Aquí, por ejemplo, vemos dos sockets físicos, cada uno con 8 núcleos y 128 GB de RAM. Cada socket está conectado a su propia porción de memoria. Esto es lo que llamamos una arquitectura NUMA: cada CPU accede más rápido a su “propia” memoria que a la del otro socket. Y sí, como os decía, un procesador puede acceder a la memoria del otro, pero con más latencia. Cómo cruzar la ciudad para ir al mercadona de otro barrio teniendo uno en el tuyo, se puede, pero no es lo ideal.

SQL Server es plenamente NUMA-aware desde hace muchas versiones. Y no es solo marketing. El motor entiende esta arquitectura y la usa para optimizar la asignación de memoria, la ejecución de tareas en paralelo y la gestión de schedulers. Todo esto siempre y cuando no le pongamos la zancadilla con configuraciones absurdas.

Planificación y schedulers: cómo SQL Server reparte el trabajo

Cada nodo NUMA tiene un conjunto de schedulers, que no son otra cosa que planificadores de hilos (threads). Para ser lo más eficiente posible, SQL Server intenta ejecutar los hilos en el mismo nodo donde se asignaron, y acceder a la memoria local del mismo. Si la información está bien distribuida, esto reduce el tráfico entre nodos y mejora la latencia general. Pero si metemos la pata, por ejemplo fijando la afinidad de forma manual y sin criterio, podemos forzar al motor a comportarse como un repartidor de pizzas desorientado: yendo de un barrio a otro sin sentido y perdiendo tiempo en cada esquina.

Además, cada instancia de SQL Server crea un grupo de trabajo por cada nodo NUMA visible. Y si usamos el modo de memoria comprimida, las decisiones de qué nodo usa qué buffer pool se vuelven aún más relevantes. Ignorar esto es como jugar al ajedrez sin mirar el tablero. Puede parecer divertido, pero termina mal.

El efecto de un mal diseño NUMA

Cuando un servidor tiene múltiples sockets físicos, es muy probable que cada socket represente un nodo NUMA. Pero algunos sistemas operativos y BIOS permiten desactivar o modificar esta topología. Resultado: servidores con 256 núcleos que se ven como un único nodo NUMA. ¿Y eso qué implica? Pues, para empezar, que SQL Server no puede distribuir sus schedulers de forma eficiente. El escalado se resiente, la contención de recursos aumenta y las consultas paralelas empiezan a hacer cosas raras.

¿Has visto alguna vez una consulta que parece ir más lenta cuanto más CPUs tiene disponibles? Bienvenido al infierno del mal NUMA. Y sí, hay admins que creen que poner más CPUs siempre mejora el rendimiento. También hay quien piensa que una tabla de log no necesita índices. Vivir para ver.

Las virtualizaciones y sus trampas con NUMA

Ah, la virtualización. Ese mundo donde puedes tener 64 vCPU repartidas en 2 nodos NUMA virtuales y no saber por qué tu SQL Server tiene el rendimiento de un 486 con resaca. Los hipervisores serios (como VMware, Hyper-V o, incluso, Proxmox) permiten configurar el número de nodos NUMA expuestos a la máquina virtual. Pero si dejas esto en manos de un “especialista” que nunca ha leído una página del “whitepaper de arquitectura NUMA en SQL Server” (sí, no solo existe, cada fabricante tiene uno propio), lo normal es que termines con un entorno virtualizado más caótico que una tabla sin clave primaria.

Por eso, cuando trabajamos con entornos virtualizados, conviene revisar cuidadosamente cómo están asignados los núcleos físicos, cuántos nodos NUMA ve la VM y cómo se está presentando la memoria. SQL Server lo detectará, pero no puede arreglar por sí solo una chapuza.

¿Y qué hay del NUMA en SQL Server en Azure?

Pues aquí el tema se vuelve más oscuro. Microsoft no publica (con detalle) la topología NUMA exacta de sus VMs, pero en general puedes asumir que, en las series más potentes, hay más de un nodo. Las VMs con más de 16 vCPU casi siempre están divididas en al menos dos nodos NUMA virtuales. ¿Cómo lo comprobamos? Ejecutando SELECT * FROM sys.dm_os_nodes y observando el campo memory_node_id. Si ves más de un nodo con memory_node_id distinto de 64 (el de DAC), estás en terreno NUMA.

Por tanto, cuando afinamos instancias en Azure, conviene monitorizar la distribución de la carga entre nodos. A veces, ciertas consultas intensivas pueden estar trabajando siempre sobre el mismo nodo, provocando un cuello de botella local mientras el resto del servidor está de paseo.

Configuraciones de NUMA recomendadas

Si el servidor tiene una topología NUMA bien definida, lo mejor que podemos hacer es dejar que SQL Server gestione sus schedulers y memoria. No toques la afinidad de CPU salvo que tengas un motivo muy claro. Y por favor, no uses MAXDOP sin entender cómo afecta a los nodos. Un mal MAXDOP puede anular por completo los beneficios de NUMA, provocando saltos de memoria y escalado ineficiente.

También hay que considerar Resource Governor, que puede fijar workloads a ciertos nodos, o las nuevas opciones de Soft-NUMA (a partir de SQL Server 2016), útiles cuando el hardware ofrece más núcleos por nodo de los que SQL Server gestiona de forma eficiente por defecto.

Y si alguien propone usar lock pages in memory sin revisar la topología NUMA antes, haceos un favor: quitadle los permisos.

Conclusión

NUMA no es un problema. Es una característica muy potente. Pero como toda característica avanzada, si no la entendemos puede convertirse en un dolor de cabeza. En entornos de producción con alta carga, especialmente con muchos núcleos y grandes volúmenes de memoria, ignorar NUMA es como hacer tuning con los ojos vendados.

La solución no es complicarse la vida configurando todo a mano sin necesidad, sino entender cómo se comporta SQL Server en nuestro entorno y dejar que optimice… siempre que el terreno no esté lleno de minas.

No lo digo yo, lo dice la ciencia.

Espero que este artículo te haya resultado útil e interesante. Si tienes alguna duda o comentario, no dudes en contactarnos en Twitter o por mail o dejarnos un mensaje en los comentarios de aquí abajo. Y recuerda que también tenemos un grupo de LinkedIn al que te puedes unir.

Publicado por Roberto Carrancio en Cloud, Rendimiento, SQL Server, 0 comentarios

¿Por qué los linked server rinden tan mal?

Pocas tecnologías han generado tanto rechazo silencioso como los linked servers en SQL Server. Todos los hemos usado alguna vez. Algunos hasta han intentado montar arquitecturas enteras con ellos, como si fueran túneles mágicos entre bases de datos. Y al principio todo parece funcionar… hasta que dejas de hacer pruebas con tablas de 100 filas y llega la realidad con sus millones. Entonces empieza el verdadero drama.

Hoy vamos a entrar al barro y a entender por qué los linked servers rinden tan mal, qué está pasando por debajo y qué alternativas tenemos cuando necesitamos algo que se parezca a un acceso remoto entre instancias. Pero, antes de abrir el quirófano y diseccionar por qué rinden tan mal, conviene repasar qué son exactamente.

¿Qué es un linked server?

Un linked server es una funcionalidad de SQL Server que nos permite acceder a datos almacenados en otro origen, como si fuera parte de nuestra propia instancia. Ese origen puede ser otra instancia de SQL Server, una base de datos Oracle, un Excel, un archivo Access o cualquier cosa que tenga un proveedor OLE DB compatible. Básicamente, nos permite ejecutar consultas distribuidas, mezclando datos de aquí y de allá, sin necesidad de ETL ni procesos intermedios.

Desde el punto de vista del T-SQL, un linked server actúa como un alias remoto: podemos hacer SELECT o incluso INSERT, UPDATE y DELETE sobre objetos que realmente viven en otro servidor. Todo a través de una conexión que, en apariencia, es transparente. Y aquí está el engaño.

Porque aunque la sintaxis parezca sencilla y todo pinte bien en la teoría, por debajo SQL Server tiene que hacer auténticas acrobacias para que eso funcione. Y, como veremos, muchas veces no lo consigue sin romperse una pierna por el camino.

Linked Server o lo que parece una buena idea en realidad es una trampa

El concepto es tentador. Con un linked server podemos conectarnos desde una instancia de SQL Server a otra, e incluso a otros motores de base de datos, como si todo estuviera en la misma base. Basta con un SELECT * FROM [ServidorRemoto].[Base].[Esquema].[Tabla] y listo. Bonito, directo, sin middleware.

Claro, si obviamos que la consulta puede tardar más que una auditoría fiscal y que la mitad de las optimizaciones que teníamos en mente se van por el desagüe.

El optimizador no es adivino

Uno de los mayores problemas de rendimiento viene de cómo SQL Server construye el plan de ejecución cuando hay un linked server de por medio. El optimizador necesita estadísticas para tomar decisiones inteligentes, pero cuando apuntamos a un servidor remoto, las estadísticas simplemente no están ahí. SQL Server no sabe cuántas filas hay, ni cuán selectiva es una condición, ni si merece la pena hacer un join remoto o traerse toda la tabla localmente.

¿Y qué hace cuando no sabe? Apuesta. Y como buen jugador conservador, apuesta mal.

Acaba generando planes de ejecución mediocres, que podrían parecer aceptables en una tabla de juguete, pero que se vuelven un desastre cuando la tabla tiene un volumen real. ¿El resultado? Lecturas innecesarias, joins ejecutados en el servidor equivocado y un tráfico de red digno de una transferencia de backups.

Linked Server PUSH vs PULL

Otro elemento clave es cómo SQL Server decide si “empuja” partes de la consulta al servidor remoto (lo que se conoce como pushing de consultas) o si tira de los datos hacia el local (pulling). Idealmente, querríamos que SQL Server enviase una subconsulta bien formada al servidor remoto, para que allí se ejecute lo que tiene sentido y solo nos devuelva lo necesario. Algo así como el plegado de consultas de Power BI.

Pero no. Muchas veces SQL Server prefiere traerse toda la tabla (sí, toda) al servidor local, y luego aplicar filtros, joins o agregaciones. Porque eso de optimizar entre servidores diferentes le cuesta. Y mucho.

Si alguna vez has hecho un SELECT COUNT(*) contra un linked server y has notado que tarda minutos en devolver un número, ya sabes por qué: se está trayendo todas las filas. A pelo.

El drama del Linked Server Provider

Detrás de cada linked server hay un proveedor OLE DB. Y no todos son iguales. Algunos soportan operaciones remotas de forma más o menos decente. Otros se comportan como si los hubiera programado un becario en prácticas en 1998.

Por ejemplo, el proveedor nativo de SQL Server a SQL Server (SQLNCLI o MSOLEDBSQL) tiene ciertas optimizaciones, pero ni con esas nos salva del todo. Ahora bien, si conectamos a Oracle, MySQL o, que no tengáis que sufrirlo, Access, el comportamiento puede ser completamente errático. Y la culpa, en parte, es del proveedor.

Si el proveedor no soporta pasar consultas completas o no permite ciertas operaciones, SQL Server lo suple como puede: trayendo filas, aplicando funciones en local, y rezando para que la red no esté saturada.

Transacciones distribuidas: el infierno del Linked Server

Si a alguien se te ocurre la brillante idea de meter una transacción que toque un linked server, prepárate. Entramos en terreno de las transacciones distribuidas, y con ello en el mundo de MSDTC (Microsoft Distributed Transaction Coordinator), uno de los servicios más temperamentales de Windows.

¿Funciona? A veces. ¿Es rápido? Ni de lejos. ¿Es seguro? Mejor no responder. Configurar MSDTC entre servidores, sobre todo en entornos con firewalls o clusters, es un vía crucis. Y aunque consigas que funcione, el rendimiento se desploma por la sobrecarga que supone coordinar commit y rollback entre servidores.

JOINs remotos: lo peor que puedes hacer por un Linked Server

Uno de los errores más frecuentes (y más costosos) es hacer joins entre una tabla local y otra remota. En muchos casos, SQL Server se trae la tabla entera del servidor remoto al local y luego hace el join. Si la tabla remota tiene 10 millones de filas y solo necesitábamos 5, mala suerte. Ya es tarde.

El problema se agrava si el join es sobre columnas sin índices en el remoto, o si las condiciones están ocultas tras funciones (como CAST, CONVERT o UPPER). SQL Server no es capaz de generar una consulta remota eficiente y recurre al “me lo traigo todo y ya lo filtro aquí”. Un plan perfecto si tienes acciones del proveedor de ancho de banda.

¿Hay alguna solución?

Sí, pero no mágica. La primera es no usar linked servers para consultas complejas o de alto volumen. Son útiles para tareas administrativas, sincronizaciones puntuales o lecturas ligeras. Pero si necesitas integrar datos entre sistemas, mejor piensa en otras alternativas.

Replicación, ETL, servicios web o incluso bases de datos distribuidas con lógica de federación (sí, esas cosas raras de Azure SQL) pueden ser opciones más razonables. También puedes optar por staging: traer datos relevantes a una tabla temporal o staging local antes de hacer las operaciones serias.

Otra alternativa, cuando no hay más remedio, es escribir consultas distribuidas con OPENQUERY. Esto obliga a que la consulta se ejecute remotamente, evitando que SQL Server decida hacer el pull de datos. No es bonito, pero al menos sabes lo que estás haciendo.

Y, por supuesto, nunca, nunca asumas que lo que funcionó en desarrollo (con 1.000 filas) escalará igual en producción (con 100 millones). No con linked servers. No hoy. No nunca.

Conclusión

Los linked servers tienen su lugar, pero no es en el rendimiento. Son una herramienta más, no la solución universal. Cuando los usamos sin entender sus limitaciones, el castigo no tarda en llegar. Lo hemos visto demasiadas veces: servidores que colapsan, redes saturadas, y consultas que mueren de inanición esperando datos que jamás deberían haber salido del servidor remoto.

¿Se pueden usar? Claro. Pero como todo en SQL Server, con cabeza, y sabiendo que a veces es mejor copiar datos que pretendiendo unir mundos que no están hechos para unirse en tiempo real.

Porque sí, puedes hacer joins entre servidores remotos, pero también puedes correr descalzo por un campo de cactus y ninguna de las dos opciones es recomendable

Si tenéis alguna duda o sugerencia, podéis dejarla en Twitter, por mail o dejarnos un mensaje en los comentarios. Y recuerda que también tenemos un grupo de Telegram y un canal de YouTube a los que te puede unir. ¡Hasta la próxima!

Publicado por Roberto Carrancio en Cloud, Rendimiento, SQL Server, 0 comentarios

¿Qué es CLR y por qué deberías limitar su uso?

Hay tecnologías en SQL Server que parecen diseñadas por y para gente que odia SQL. Una de ellas es CLR (Common Language Runtime). Si alguna vez has pensado “¿y si meto C# dentro de una base de datos?”, enhorabuena: acabas de invocar al diablo del rendimiento. Pero, como todo en este mundo, si se usa con criterio y sentido común (sí, eso que tan poca gente aplica), puede aportar soluciones que de otro modo serían infernales de implementar en T-SQL.

¿Qué demonios es CLR y por qué está dentro de SQL Server?

CLR es un motor de ejecución de .NET. Desde SQL Server 2005 tenemos la opción de crear procedimientos almacenados, funciones, triggers y tipos definidos por el usuario usando lenguajes .NET como C# o VB.NET. Esto permite extender la funcionalidad de T-SQL cuando éste se queda corto. Y sí, hay que reconocerlo, T-SQL se queda corto en ciertas áreas, como el procesamiento intensivo de texto, operaciones matemáticas complejas o manipulación avanzada de estructuras de datos.

Ahora bien, que algo se pueda hacer no significa que deba hacerse. De hecho, habilitar CLR en una instancia es como abrir una puerta lateral en un castillo: puede estar bien si sabes quién entra y sale, pero si la dejas abierta, prepárate para las sorpresas.

Activar CLR: el primer pecado

Por defecto, CLR viene deshabilitado. Hay que habilitarlo explícitamente:

Hasta aquí todo bien. Pero luego llega la decisión importante: ¿qué nivel de seguridad vamos a aplicar? Aquí es donde muchos pecan por ignorancia o por prisa. SQL Server permite establecer niveles de seguridad en los ensamblados: SAFE, EXTERNAL_ACCESS y UNSAFE.

  • SAFE es la opción por defecto y la más limitada. Permite usar solo código seguro dentro del sandbox de SQL Server. Vamos, que no puedes acceder al sistema de archivos ni hacer llamadas a red.
  • EXTERNAL_ACCESS permite acceso al sistema, como archivos o recursos de red. Requiere permisos adicionales en la base de datos y en el servidor.
  • UNSAFE es exactamente lo que parece: la carta blanca para que alguien con tiempo libre y ganas de destruir te monte un agujero de seguridad monumental. Desde abrir un puerto TCP hasta modificar binarios en disco. Y si el servidor ejecuta SQL Server con permisos de sistema, el daño potencial es ilimitado.

El resumen es simple: si usas EXTERNAL_ACCESS o UNSAFE y no sabes exactamente lo que estás haciendo, ya puedes ir llamando al responsable de seguridad para una charla “interesante”.

¿Y por qué usar CLR? ¿Realmente aporta algo?

En ocasiones, sí. Hay escenarios donde CLR no solo tiene sentido, sino que puede ser la solución óptima. Por ejemplo:

  • Procesamiento de texto complejo: Las expresiones regulares en T-SQL son una promesa aún. Mientras que estamos empezando a verlas en las previews de Azure SQL y SQL Server 2025, en C# puedes usarlas sin volverte loco. Una función CLR que use Regex.Match puede reemplazar cientos de líneas de T-SQL feo y lento.
  • Cálculos matemáticos avanzados: ¿Has intentado hacer operaciones trigonométricas complejas o cálculos estadísticos avanzados con T-SQL? No, ¿verdad? Pues eso. CLR te permite usar librerías de .NET que hacen esto sin romperte la cabeza. Aunque, pensándolo bien, ¿no preferirías usar python o R para estas cosas?
  • Manejo de estructuras como arrays o diccionarios: Aunque con SQL Server 2022 y sus mejoras en JSON y XML estas necesidades han bajado, aún hay casos donde un buen Dictionary<string, List<int>> en C# resuelve en milisegundos lo que en T-SQL requeriría un máster.
  • Performance en funciones escalares: Una función escalar en T-SQL puede ser un veneno para el rendimiento si se ejecuta por cada fila de una tabla grande. En CLR, ese impacto puede reducirse significativamente.

Eso sí, si el único motivo para usar CLR es que “yo sé C# y no me gusta T-SQL”, lo que necesitas no es un CLR, es un cambio de trabajo.

Cómo crear un ensamblado CLR sin invocar a Satán

Veamos el proceso básico:

Primero escribes el código en C# (en Visual Studio o lo que uses). Luego compilas el ensamblado (DLL) y lo subes a SQL Server con CREATE ASSEMBLY. Por último creas la función o procedimiento que lo expone. Un ejemplo sencillo:

Código C#:

Compilas esto como DLL y lo subes:

Y voilà. Ya puedes usar dbo.ReverseString(‘hola’).

¿Dónde rompe CLR las cosas y por qué?

Ahora hablemos de los pecados originales del CLR. El primero es la dificultad de mantenimiento. El código está fuera del ámbito natural del DBA. Si mañana hay que parchear un bug en ese ensamblado, necesitas recompilar, volver a subirlo y cruzar los dedos para que no tengas dependencias rotas. Además, muchas veces ni siquiera se versionan correctamente. Y sí, lo hemos visto en producción. Más veces de las que nos gustaría.

Segundo, el tema de la seguridad. Un ensamblado con UNSAFE puede hacer cualquier cosa en el sistema operativo. Y cuando decimos cualquier cosa, es cualquier cosa. ¿Quieres que tu base de datos escanee el disco C:? Puedes hacerlo. ¿Deberías hacerlo? No. Nunca.

Tercero, el rendimiento. Aunque en algunos escenarios el CLR escala mejor que T-SQL (especialmente en funciones escalares y algoritmos complejos), introducir CLR sin medir su impacto real es como poner un turbo a un coche sin frenos. Necesitas pruebas serias, monitorización con Extended Events o Profiler, y entender bien los contextos de ejecución y memoria.

CLR y los entornos modernos

¿Sigue teniendo sentido usar CLR en 2025? Depende. SQL Server ha mejorado mucho en áreas como funciones en línea, JSON, XML, y hasta integración con Python y R vía Machine Learning Services. Muchas cosas que antes requerían CLR ahora se pueden hacer dentro del propio SQL Server sin salir del ecosistema T-SQL.

Pero aún hay casos de uso válidos: si necesitas lógica reutilizable, validaciones complejas, o consumir recursos externos con control, puede ser una herramienta útil. Eso sí, no abuses. Lo que empieza como una solución elegante puede acabar como un infierno de dependencias, DLLs perdidas y bugs imposibles de depurar.

Conclusión

El CLR no es el enemigo. El enemigo es usar herramientas que no entendemos solo porque «molan» o porque «así lo hacemos en .NET». SQL Server permite muchas cosas, pero no todas son recomendables. Si vas a meter CLR en tu arquitectura, hazlo con cabeza, documentación, versiones bien gestionadas y, por supuesto, tests.

Y si estás usando funciones CLR porque no sabías cómo hacerlo en T-SQL… mejor sigue leyendo el blog. Tenemos artículos sobre expresiones regulares y otras maravillas menos propensas a prenderle fuego a tu entorno productivo.

Porque sí, puedes meter C# en SQL Server, y también puedes meter un gato en una lavadora. Pero no deberías.

Si tenéis alguna duda o sugerencia, podéis dejarla en Twitter, por mail o dejarnos un mensaje en los comentarios. Y recuerda que también tenemos un grupo de Telegram y un canal de YouTube a los que te puede unir. ¡Hasta la próxima! 

Publicado por Roberto Carrancio en Cloud, Rendimiento, SQL Server, 0 comentarios

¿Qué es xp_cmdshell y por qué deberías limitar su uso?

Hay ciertas funciones en SQL Server que tienen más leyenda que documentación, y una de ellas es xp_cmdshell. Mencionarla en una reunión de seguridad es como decir “TRIGGER” en una daily de DBAs: inmediatamente empiezan los sudores fríos. Pero como buenos profesionales de bases de datos, no podemos permitirnos el lujo de ignorarla. Hay que entender qué hace, cómo se usa (o se abusa), y sobre todo por qué en la mayoría de los casos deberíamos tenerla bien atada, o mejor aún, desactivada.

¿Qué es xp_cmdshell?

Para los recién llegados (o para los que han tenido la suerte de no cruzárselo nunca), xp_cmdshell es un extended stored procedure que permite ejecutar comandos del sistema operativo directamente desde SQL Server. Tal cual. Es decir, desde una sesión de SQL puedes invocar comandos como si estuvieras en la consola de Windows: copiar ficheros, lanzar scripts batch, ejecutar aplicaciones externas… o destruir medio sistema si tienes permisos suficientes y pocas luces.

El siguiente ejemplo es inocente (más o menos), pero ilustra la idea:

SQL ejecuta el comando y te devuelve el resultado como si estuvieras en una consola de MS-DOS de los 90. Y sí, es tan peligroso como suena.

¿Para qué se usa xp_cmdshell legítimamente?

Hay quien justifica su uso con casos reales: automatización de procesos que interactúan con el sistema de archivos, lanzamiento de tareas administrativas, scripts que integran SQL con otros procesos batch o herramientas de terceros. Incluso estos ojos han visto escenarios donde se usaba para invocar clientes FTP y descargar archivos que luego se importaban con BULK INSERT o mover backups entre servidores.

Y aunque todo esto se puede hacer, la pregunta es: ¿debería hacerse así? Spoiler: no. O al menos, no sin un análisis serio de riesgos y alternativas. Porque una cosa es poder, y otra muy distinta es tener criterio.

La seguridad, el verdadero problema de xp_cmdshell

El mayor problema de xp_cmdshell no es su existencia, sino su potencia. Ya sabes, eso de que un gran poder conlleva una gran responsabilidad. Este procedimiento ejecuta los comandos en el contexto de seguridad de la cuenta del servicio de SQL Server, lo que, si no se ha configurado adecuadamente, puede significar ejecutar con privilegios elevados. Y eso convierte cualquier brecha de seguridad en una puerta abierta al sistema operativo, red y mil cosas más.

Por defecto, xp_cmdshell viene desactivada. Microsoft no es tonta, y sabe que dejar esto habilitado por defecto sería como enviar servidores a producción con el firewall desactivado. Pero como casi todo en SQL Server, se puede activar fácilmente:

Y una vez activada, el riesgo está servido. Cualquier usuario que tenga permisos para ejecutarla puede comprometer el servidor. Si encima tiene permisos sysadmin (y aún hay entornos donde todo el mundo es sysadmin «porque así funciona»), la fiesta está asegurada.

¿Se puede usar xp_cmdshell de forma segura?

La teoría dice que sí. Microsoft introdujo ciertas medidas para controlar su uso. Por ejemplo, si el usuario no es sysadmin, se puede configurar una cuenta proxy mediante el procedimiento almacenado sp_xp_cmdshell_proxy_account que limita los permisos con los que se ejecutan los comandos.

Esto permite definir una credencial para que el comando xp_cmdshell se ejecute con los permisos de ese usuario en lugar de usar la cuenta del servicio. Pero seamos serios: ¿cuántas veces se hace esto bien en entornos reales? ¿Cuántas veces se revocan luego los permisos cuando ya no hacen falta? ¿Y cuántos servidores en producción tienen la proxy account configurada pero también usuarios sysadmin “temporales” que llevan ahí desde 2016?

Además, aunque configures la cuenta proxy correctamente, sigue siendo un punto de entrada que puede explotarse si no se audita y controla su uso. El riesgo persiste, solo se disfraza de buena práctica.

Alternativas reales y razonables a xp_cmdshell

Casi todo lo que se hace con xp_cmdshell se puede hacer mejor y con más control desde fuera de SQL Server. Si necesitas mover archivos, usar PowerShell o scripts externos lanzados desde un agente de automatización como SQL Server Agent o un sistema de orquestación decente (¿alguien ha dicho Azure Data Factory?) es mucho más razonable.

Para transferencias FTP o SFTP, hay herramientas modernas que no requieren meter comandos del sistema operativo en medio del motor de base de datos. Y si lo que se busca es coordinación entre procesos, los servicios de Windows, los job schedulers o incluso Integration Services son alternativas mucho más limpias.

SQL Server es un motor de bases de datos, no un sistema operativo ni un centro de comandos. Empezar a usarlo como tal es como usar un bisturí para abrir latas: técnicamente se puede, pero no es lo suyo y probablemente acabes con un desastre.

Auditar, controlar, eliminar

Si estás heredando un sistema y no sabes si xp_cmdshell está activa, revísalo. Yo personalmente es de las primeras cosas que compruebo. Para verlo es tan fácil como ejecutar:

Si el valor de «config_value» es 1, está habilitado. Si no se está utilizando (y muchas veces no lo está, pero nadie se atreve a desactivarla “por si acaso”), desactívalo sin piedad:

Y si alguien protesta, que traiga el caso de uso documentado, el análisis de riesgos y una alternativa propuesta. Si no puede justificarlo, no es necesario. Punto. No admito discusiones.

Además, si en algún entorno necesitas activarlo temporalmente, documenta cuándo y por qué, y asegúrate de desactivarla después. Y lo más importante: registra quién tiene permisos para usarlo, y controla ese acceso como si fuera el código para activar el botón rojo nuclear. Porque en cierto sentido, lo es.

Conclusión

xp_cmdshell es una herramienta poderosa, pero como todas las herramientas poderosas, puede causar más daño que beneficio si se usa mal. No está pensada para ser parte habitual de ningún flujo de trabajo moderno en SQL Server. Su existencia tiene sentido en contextos muy controlados, con auditoría, justificación y planificación. Pero la realidad es que en la mayoría de los entornos en los que aparece, lo hace como un parche rápido, una chapuza heredada o un atajo que algún valiente implementó sin medir consecuencias.

Limitar o eliminar su uso no solo mejora la seguridad del entorno, sino que obliga a buscar soluciones más sostenibles, limpias y profesionales. Porque si nuestra base de datos necesita ejecutar scripts del sistema para funcionar, igual el problema no está en xp_cmdshell, sino en cómo hemos diseñado la arquitectura.

Y si aún piensas que «no pasa nada por tenerla habilitada», revisa tus backups. Puede que los necesites antes de lo que crees, o que alguien los haya borrado desde xp_cmdshell.

Si tenéis alguna duda o sugerencia, podéis dejarla en Twitter, por mail o dejarnos un mensaje en los comentarios. Y recuerda que también tenemos un grupo de LinkedIn y un canal de YouTube a los que te puede unir. ¡Hasta la próxima!

Publicado por Roberto Carrancio en SQL Server, 0 comentarios

Búsquedas semánticas con IA en SQL Server 2025

En algún momento entre pelear con índices zombis y migraciones eternas, Microsoft ha decidido que SQL Server también podía ser inteligente. Y no me refiero al tipo de inteligencia que esperas de un MERGE bien hecho (que ya sabemos que es difícil de ver), sino a IA de verdad: modelos de lenguaje, embeddings, vectores y búsquedas semánticas integradas directamente en el motor. Sí, en nuestro motor de base de datos favorito.

En este artículo vamos a desmenuzar la nueva funcionalidad de SQL Server 2025 que permite integrar modelos de IA para realizar búsquedas semánticas directamente desde SQL. Sin inventos raros y, lo más sorprendente, sin tener que abandonar nuestro entorno habitual. Ahora podemos chatear con nuestros datos sin salir del Management Studio.

Inteligencia artificial en SQL Server: la cosa se pone serIA

(Perdón por el chiste. Es malísimo, lo sé)

Esto no es un plugin experimental ni una feature de análisis de datos metida con calzador. Microsoft ha incorporado capacidades de IA directamente en el motor de SQL Server. Y eso significa que podemos invocar modelos de lenguaje desde procedimientos almacenados, generar embeddings, indexarlos y hacer comparaciones semánticas en caliente.

Y todo sin que los datos salgan del servidor. La seguridad y el rendimiento siguen siendo prioridad: lo que hacemos es pasar una consulta a un modelo que genera un vector (el embedding) y lo compara con los vectores previamente almacenados localmente. Resultado: respuestas rápidas, semánticamente relevantes y sin montar un chiringuito en Azure (solo unos pocos clicks).

Vectores, embeddings y cosenos: la IA no entiende palabras, entiende números

Esto tiene que quedar claro desde el principio, la IA no trabaja con texto. Aunque lo parezca, la IA no sabe leer. Internamente trabaja con vectores, que son representaciones matemáticas de conceptos. Un vector es simplemente una lista ordenada de números (normalmente de 1536 dimensiones) que representa el “significado” de algo.

Cuando decimos “bicicleta para descenso de montaña”, un modelo de lenguaje genera un vector que encapsula ese significado. Ese vector es un embedding. Y lo interesante es que podemos comparar ese embedding con otros ya almacenados, usando la similitud de coseno, para encontrar los conceptos más cercanos.

Cuanto más cercano es el ángulo entre dos vectores, más parecido es su significado. No hay magia. Hay trigonometría. Pero no te preocupes, que no vas a tener que calcularlo tú: eso se lo dejamos al motor, que para eso está.

¿Cómo implementar esta IA?

En mis pruebas he usado AdventureWorks, cómo no. Desde la tabla de productos, extraemos las descripciones y, a esas descripciones, les generamos embeddings usando un procedimiento almacenado que recibe un texto y lo envía al modelo modelo en Azure OpenAI (podría ser otro, incluso en local, pero aquí opte por ir a lo fácil y rápido). Importante guardar estos embeddings en una tabla separada: más limpio y mejor rendimiento.

Por último, creamos un segundo procedimiento almacenado que recibe una frase, genera su embedding con el SP anterior y, una vez obtiene su embedding lo compara con los embeddings almacenados en base para devolver los más cercanos. Y sí, todo desde SQL. Llamadas REST mediante, pero dentro de una SP.

Así obtenemos resultados en milisegundos. Eso es lo que tarda en calcular el embedding de una petición y compararlo con los datos. Rápido, elegante, sin ETLs de por medio y sin mover los datos de casa (siempre que uses un modelo local, claro).

¿Qué es esto de las búsquedas semánticas? La magia de la IA en SQL

Este es el verdadero factor diferenciador. No estamos hablando de una búsqueda con like ni de índices de texto completo (Full Text Indexes). Los embedding representan el significado de las palabras de manera que aspectos como sinónimos o incluso, el idioma de la búsqueda dejan de ser un impedimento.

En mis pruebas las descripciones de producto están en inglés, francés o incluso en chino. Yo he probado con prompts en español, inglés e incluso con redacciones ambiguas. El modelo entiende el significado, no la forma. Así que da igual si pides “bicicleta de descenso” o “bike for downhill mountain racing”: el embedding será muy similar y los resultados coherentes.

Una vez que te acostumbras, el LIKE te empieza a parecer una piedra tallada con cincel.

Aplicaciones reales más allá del hype

Vale, comparar descripciones de productos es “la demo fácil”. Pero no significa que no tenga valor ni que esto no se pueda llevar mucho más allá.

Gracias a esta funcionalidad puedes recomendar artículos relacionados en tu tienda web. Pero no es el único caso de uso. 

¿Tienes transcripciones de llamadas de soporte técnico? Embeddings. ¿Tienes feedback de clientes en la web? Embeddings. ¿Quieres analizar opiniones para saber si tu producto gusta o no? Más embeddings. Puedes clasificar sentimientos, detectar patrones de insatisfacción, anticipar problemas o simplemente automatizar búsquedas que hasta ahora eran imposibles sin intervención humana.

Y todo desde SQL Server. Sin montar pipelines, sin exportar a otro sistema, sin líos innecesarios. Aquí, en casa. Y eso, para un DBA con años de cicatrices, es música celestial pero también asusta. ¿Cómo va a impactar esto en nuestros sistemas? Solo el tiempo y el uso en cada escenario lo dirá.

Comparaciones por dentro: un vistazo rápido al cálculo de la IA

[Modo TryHard Activado] Por si tienes curiosidad matemática (o simplemente quieres saber si todo esto tiene sentido), el cálculo de similitud se basa en cosenos. Lo que estamos haciendo es comparar dos vectores, en nuestro caso el del prompt y el del producto. Para eso lo que se hace es calcular su producto escalar, sus magnitudes, y aplicar la fórmula del coseno.

Similitud = cos(θ) = (A·B) / (||A|| * ||B||)

Y la distancia, por si necesitas algo más crudo, es simplemente 1 – similitud. Cuanto más cercana a cero, más similares. Cuanto más cerca de uno, más distintos.

¿Y qué hacemos con eso? Ordenamos por similitud y nos quedamos con los más relevantes. No hay magia negra. Es álgebra lineal.

Conclusión

Esto no es hype. No es una demo para sorprender en eventos. Es una funcionalidad real, integrada, segura y rapidísima que cambia la forma en la que interactuamos con los datos.

SQL Server 2025 ha dejado de ser solo un motor relacional. Ahora también es un intérprete semántico. Y eso abre puertas que antes ni sabíamos que existían.

Lo dicho: si pensabas que lo habías visto todo en SQL, ya puedes ir quitándote esa idea de la cabeza. Y si no empiezas a trastear con embeddings, búsquedas semánticas y llamadas a modelos de lenguaje… no digas luego que no te avisamos.

Esto ha venido para quedarse. Y aquí, como siempre, trataré de analizarlo en condiciones.

Si tenéis alguna duda o sugerencia, podéis dejarla en Twitter, por mail o dejarnos un mensaje en los comentarios. Y recuerda que también tenemos un grupo de LinkedIn y un canal de YouTube a los que te puede unir. ¡Hasta la próxima!

Publicado por Roberto Carrancio en Cloud, SQL Server, 0 comentarios

Roles de base de datos en SQL Server

Después de explorar los roles de servidor predefinidos en SQL Server, es lógico continuar analizando el otro gran componente del modelo de permisos: los roles de base de datos. Mientras que los primeros afectan a toda la instancia, estos últimos actúan dentro de una base de datos concreta, permitiéndonos aplicar controles más finos sobre quién puede hacer qué, cómo y dónde dentro del entorno de datos.

Gracias a los roles de base de datos, podemos organizar el acceso de usuarios, aplicaciones y servicios en función de necesidades específicas, minimizando el riesgo de accesos indebidos y facilitando la administración. Su correcta utilización es clave para implantar políticas de seguridad sostenibles y alineadas con el principio de privilegio mínimo.

¿Qué son los roles de base de datos y cómo se diferencian de los de servidor?

Los roles de base de datos son “contenedores de permisos” que se aplican dentro del ámbito de una única base de datos. Un usuario puede pertenecer a distintos roles en diferentes bases, con permisos completamente independientes. A diferencia de los roles de servidor, no otorgan privilegios sobre la instancia ni sobre otras bases de datos.

Por ejemplo, un usuario podría ser db_datareader en una base y db_owner en otra, sin que eso afecte a su capacidad de acceder a la configuración global del servidor o a otras bases no relacionadas. Para ser estrictos, cada base de datos tendrá su usuario que pertenece a sus roles y estos usuarios estarán enlazados a un mismo login.

Esta independencia permite diseñar estrategias de seguridad muy detalladas, en las que cada usuario o grupo recibe únicamente los permisos necesarios en cada base, sin arrastrar privilegios innecesarios.

Roles fijos de base de datos

SQL Server incluye una serie de roles fijos que vienen predefinidos en cada base de datos y cubren los escenarios más habituales de gestión y uso:

  • db_owner otorga control total sobre todos los objetos y permisos de la base de datos. Es el equivalente a un administrador local. Su uso debe restringirse, ya que un miembro de este rol puede concederse cualquier permiso, incluso eliminar datos o activar configuraciones peligrosas como TRUSTWORTHY.
  • db_securityadmin permite gestionar permisos, roles y pertenencias, sin acceso directo a los datos. Se utiliza en contextos donde la administración de seguridad está delegada a un equipo diferente del que desarrolla o explota la base.
  • db_accessadmin se centra en controlar qué inicios de sesión pueden acceder a la base de datos, sin permitir alterar los objetos.
  • db_ddladmin permite crear y modificar objetos, como tablas, procedimientos o funciones, pero no ejecutar o leer datos si no se concede ese permiso explícitamente.
  • db_datareader y db_datawriter permiten leer o escribir en todas las tablas y vistas de la base, respectivamente. Su uso está muy extendido en entornos donde se busca una división clara entre consumo y generación de datos.
  • db_backupoperator da acceso a realizar copias de seguridad de la base, pero no restaurarlas ni acceder al contenido.

También existen dos roles especiales diseñados para denegar explícitamente el acceso a los datos.

  • db_denydatareader impide leer cualquier tabla o vista, incluso si otros roles o permisos lo permiten.
  • db_denydatawriter bloquea la capacidad de insertar, actualizar o eliminar datos.

Además, todos los usuarios pertenecen al rol public, que funciona como contenedor de permisos comunes. Conviene auditar este rol, ya que cualquier permiso que se le conceda afectará a todos los usuarios de la base, sin excepción.

Roles definidos por el usuario: flexibilidad con control

Los roles fijos no cubren todos los escenarios. En bases de datos complejas, necesitamos diseñar roles personalizados que agrupen permisos según criterios funcionales, de negocio o de seguridad. SQL Server permite crear estos roles mediante la instrucción CREATE ROLE, y a partir de ahí podemos asignarles permisos (GRANT, DENY, REVOKE) y miembros (ALTER ROLE … ADD MEMBER).

Esto nos permite definir roles como lectura_finanzas, escritura_marketing, administrador_reportes o cualquier otro nombre que represente una necesidad específica de acceso.

Una ventaja clara de este enfoque es que facilita la administración a largo plazo: si mañana se incorpora una nueva persona al equipo de marketing, basta con agregarla al rol correspondiente, sin tener que revisar permisos individuales.

También permite mantener las políticas de seguridad documentadas, auditables y fácilmente transferibles entre entornos.

Buenas prácticas en la asignación de roles de base de datos

Diseñar una estrategia sólida de roles no consiste solo en conocer los disponibles, sino en aplicarlos con criterio. No debemos asignar permisos directamente a usuarios individuales. En su lugar, se crean roles personalizados y se asignan los permisos al rol, manteniendo la lógica de acceso desacoplada de los usuarios.

Otra recomendación es que el rol db_owner debe reservarse para tareas excepcionales o de mantenimiento. En la mayoría de los casos, podemos cubrir todas las necesidades combinando db_ddladmin, db_datareader, db_datawriter y roles personalizados.

Como ya hemos comentado antes, revisar el contenido del rol public en cada base de datos es fundamental. En muchas implementaciones antiguas se le han otorgado permisos de lectura general como solución rápida, pero esto impide auditar correctamente qué usuarios acceden a qué objetos.

Por último, documentar el propósito de cada rol, quiénes lo integran y qué permisos tiene asignados nos permitirá mantener el sistema bajo control con el paso del tiempo.

El rol inexistente db_executor: ¿Por qué no existe y cómo crearlo?

Un error común al comenzar a trabajar con SQL Server es suponer que existe un rol fijo llamado db_executor, similar a db_datareader o db_datawriter, que permita ejecutar todos los procedimientos almacenados de una base de datos. Sin embargo, SQL Server no incluye por defecto un rol con este nombre ni con ese comportamiento. Tampoco los roles db_datareader o db_datawriter permiten la ejecución de procedimientos almacenados.

Esto suele generar confusión porque ejecutar procedimientos es una necesidad frecuente, especialmente en entornos donde las aplicaciones solo deben invocar lógica encapsulada sin acceder directamente a las tablas. La buena noticia es que podemos crear este rol manualmente en cualquier base de datos y dotarlo de los permisos necesarios para cumplir esa función. Para ello, basta con ejecutar las siguientes instrucciones:

Con esto estamos creando un nuevo rol llamado db_executor y concediéndole el permiso EXECUTE sobre todos los objetos ejecutables de la base. A partir de ese momento, cualquier usuario que añadamos al rol podrá ejecutar procedimientos, funciones o scripts definidos por el usuario, sin necesidad de acceder a las tablas directamente.

Este enfoque es muy útil para separar claramente los permisos de lectura, escritura y ejecución, y encaja perfectamente con una arquitectura basada en acceso controlado mediante procedimientos almacenados. Además, permite mantener el principio de encapsulamiento: los usuarios no necesitan saber cómo se obtiene un dato, solo deben poder invocar la lógica que lo proporciona.

Aunque no sea un rol predefinido, db_executor se ha convertido en una práctica ampliamente aceptada en entornos corporativos y en desarrollos donde se prioriza la seguridad y la trazabilidad de accesos.

Conclusión

Los roles de base de datos en SQL Server nos permiten construir un modelo de seguridad sólido, escalable y alineado con las necesidades reales de uso de cada entorno. Si aprendemos a usarlos correctamente, sin abusar de db_owner, sin asignar permisos individuales y combinándolos con el uso estratégico de esquemas, dispondremos de una estructura de permisos fácil de mantener, auditar y adaptar a los cambios del negocio.

Cuando los roles de servidor y de base de datos se combinan adecuadamente, conseguimos un entorno donde la delegación de tareas y el control de seguridad no son opuestos, sino aliados.

Si tenéis alguna duda o sugerencia, podéis dejarla en Twitter, por mail o dejarnos un mensaje en los comentarios. Y recuerda que también tenemos un grupo de Telegram y un canal de YouTube a los que te puede unir. ¡Hasta la próxima! 

Publicado por Roberto Carrancio en Cloud, SQL Server, 0 comentarios