Incidencias

SQL consume mucha RAM. Solución a problemas de memoria

Bienvenidos a este tercer artículo sobre el uso que hace SQL Server de la memoria RAM. En los últimos días ya hemos visto cómo se gestiona la RAM en SQL y la configuración especial LPIM para optimizar el rendimiento en caso de presión de memoria. Pero si recordáis, en este último artículo, os decía que antes de tocar LPIM lo mejor era afrontar el problema. Por ello vamos a dedicar este artículo a ver cómo podemos detectar y afrontar problemas de consumo excesivo de memoria RAM.

Determinando el consumo excesivo de memoria

¿Realmente tenemos un problema? Esta es la principal pregunta, normalmente, a ojos del que no conoce el funcionamiento de SQL Server puede ser preocupante la gran cantidad de memoria que SQL Server suele tener reservada. Sin embargo, nosotros que somos buenos DBAs (y hemos leído el artículo sobre la RAM del otro día) sabemos que no nos podemos fiar de eso pues SQL Server siempre va a reservar toda la RAM que tenga a su disposición hasta el máximo que le hayamos asignado. Esto no quiere decir que la esté usando así que vamos a ver cómo podemos realmente darnos cuenta. 

Analizando el consumo de memoria RAM de SQL Server

SQL Server pone a nuestra disposición unas vistas de administración dinámica (dm views) que nos pueden dar cierta información sobre la RAM. Estas vistas son, según la documentación oficial, sys.dm_os_process_memory y sys.dm_os_sys_memory. Aunque a mi me gusta también consultar sys.dm_os_sys_info y sys.dm_os_performance_counters.

Vista sys.dm_os_process_memory

En esta vista podemos encontrar datos sobre la cantidad de memoria en uso y disponible en nuestro SQL Server. Podéis consultar la documentación oficial de la vista aquí. Yo os recomiendo estas:

En esta consulta de Pinal Dave, muy interesante podemos ver la memoria en uso y un par de avisos sobre presión de memoria. Si los dos avisos están en 0 es que todo está bien.

Esta otra consulta nos da un poco más de información, en ella vamos a poder ver el detalle de lo que está consumiendo la memoria RAM por parte de SQL Server:

Vista sys.dm_os_sys_memory

Esta vista de sistema nos va a dar menos variedad de información pero no por ello menos útil. A diferencia de la anterior aquí veremos los datos de memoria de nuestro servidor no solo de SQL Server. Podéis ver todas las columnas disponibles en la vista aquí, aunque yo os recomiendo esta consulta.

Vista sys.dm_os_sys_info;

Esta vista es muy interesante pues además de la memoria en uso por SQL Server nos va a mostrar una estimación de lo que SQL Server espera necesitar. Si combinado con las anteriores vemos que el valor necesitado es menor que el disponible podemos respirar tranquilos. Os dejo un ejemplo de uso sencillo:

Vista sys.dm_os_performance_counters

Esta vista nos va a mostrar todos los contadores de rendimiento, incluidos los de SQL Server. Con ella podremos tener una visión más completa de lo que está pasando. Para el caso que nos ocupa os recomiendo filtrar por la palabra memoria:

Bonus 

Además de todas estas vistas de sistema, SQL pone a nuestra disposición el comando DBCC MEMORYSTATUS. Este comando nos va a dar mucha información (demasiada) sobre todo el estado de la memoria. Está diseñado para ser una herramienta de diagnóstico para los ingenieros de soporte de Microsoft por lo que, a nosotros, simples mortales, nos va a confundir más que otra cosa. Si tienes curiosidad sobre este comando puedes pasarte por su página en los books online de SQL Server dónde lo explican en detalle.

¿Qué hago si realmente hay un problema con la memoria?

Si llegados a este punto has detectado que si que tenias un problema real con el consumo de memoria RAM, te compadezco. Estás en una situación en la que a ninguno nos gustaría estar, pero no te preocupes, vivimos de esto y es lo que nos da dinero. Sigue leyendo que aún hay más artículo para que puedas salir airoso de este marronazo.

Lo primero que tendrás que determinar es si el problema está ocurriendo ahora mismo o ya ha pasado. Si estás en el primer caso puedes hacer uso de procedimientos almacenados como sp_who3, sp_whoisactive o sp_blitzwho para determinar el consumo de memoria de cada una de las consultas en ejecución y tirar de las orejas a alguien.

Si, como me pasa a mi, en tu país también está mal visto (y hasta penado por ley) el castigo físico, analiza las consultas que más memoria consumen y trata de optimizarlas. Quizá solo te falta un índice. O a lo mejor es al revés y te sobran. O están bien definidos pero sin mantenimiento. Te aseguro que con esto de los índices vas a resolver el 70% de las incidencias que te puedas encontrar. El resto de casos puede ser debido a ordenaciones sin miedo a lo que pueda pasar o al uso de operadores como UNION, DISTINCT, etc… que cargan el resultado en memoria para eliminar registros duplicados.

Si el problema ya ha pasado y no tienes tanta suerte de acceder a las consultas en ejecución, revisa los índices que te faltan y los que no se usan que es probable que con eso lo soluciones. Te dejo por aquí todo lo que se ha hablado en este blog sobre índices.

Conclusión

Afrontar una incidencia sobre el consumo de memoria en SQL Server puede ser un desafío. Espero que con estas herramientas de diagnóstico, nativas y de terceros, podáis enfrentaros mejor a ellas. Tampoco está de más ser proactivos y revisar de vez en cuando el uso de índices para ahorrarnos problemas. Un buen mantenimiento de índices y estadísticas nos evitará más de un disgusto. Recordad que un diagnóstico y una resolución rápida son fundamentales para mantener un entorno SQL Server saludable y eficiente. La superación de estos retos garantiza un funcionamiento fluido de la base de datos y contribuye a la eficacia general de la empresa, a la satisfacción del cliente y, en última instancia, a la cuenta de resultados.

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.

CRÉDITOS: Varias de las consultas de este post son originales de Pinal Dave de SQLAuthority y del blog SQLHack

Publicado por Roberto Carrancio en Rendimiento, SQL Server, 5 comentarios

Prevenir usuarios huérfanos

En el anterior post aprendimos lo que eran y cómo corregir el problema de usuarios huérfanos, sin embargo, como es mejor prevenir que curar, vamos a aprender cómo prevenir el problema.

A modo de resumen, un usuario huérfano es el que no está relacionado con un login. Esto es muy común cuando movemos bases de datos entre diferentes servidores o cuando tenemos un sistema de alta disponibilidad que replica las bases de datos como el Always On o el Log Shipping. Aunque tengamos logins con el mismo nombre en ambos servidores no tienen el mismo SID. Como ya habréis podido adivinar para no tener más este problema deberemos asignar al login el mismo SID, pero esto solo se puede hacer recreando el login.

Averiguar el SID de un usuario por script

Lo primero que haremos será crear el login normalmente en uno de los servidores. Si ya tenemos los logins creados en ambos servidores lo borraremos de uno de ellos. Con el login creado en solo uno de los servidores usaremos este script para ver el SID:

select name, sid from sys.sql_logins

Copiaremos el sid de nuestro login y cuando vayamos a crearlo en el otro servidor le indicaremos que use ese SID de la siguiente manera

CREATE LOGIN batman WITH PASSWORD = 'G0th@m', SID = 0x8FB57BD6DA61BA40ABAB2A41DDC91A41

Scriptar la contraseña

En el ejemplo anterior hemos creado un login con un SID concreto y una contraseña. Hemos podido hacer esto porque conocíamos la contraseña del usuario pero, en la vida real, esto no siempre es tan bonito. Con SQL no vamos a poder ver las contraseñas de los usuarios en texto plano pero, esto tampoco significa que no podamos hacer nada. Usando la misma vista de antes sys.sql_logins podemos obtener la contraseña cifrada.

select name, sid, password_hash from sys.sql_logins

Con el HASH de la contraseña y el SID recrearemos el login de la siguiente manera:

CREATE LOGIN batman WITH PASSWORD = 0x0200B240435023921FCBA909DCF2136C27F81D0A4BEADBFBB5286E0511C8CF490BFAB9002EE881A8E7423195571D933AB189A9CB3EB5109C78A0789436811F6C833D8233B8B6 HASHED , SID = 0x8FB57BD6DA61BA40ABAB2A41DDC91A41

Copia masiva de logins

Para recrear varios inicios de sesión de golpe podemos hacer uso del procedimiento almacenado sp_help_revlogin. Para poder usarlo primero copiaremos el código del procedimiento desde la web oficial de Microsoft y lo ejecutaremos en nuestra instalación. Con ejecutar el procedimiento tendremos el script para recrear todos los logins con el mismo SID y contraseña.

Conclusión

Hemos aprendido cómo saber el SID y la contraseña cifrada de nuestros logins para transferirlos a otros servidores sin miedo a generar usuarios huérfanos. Esto es muy útil cuando mueves bases de datos entre servidores de manera periódica, como cuando refrescas un servidor de preproducción pero es imprescindible en instalaciones de alta disponibilidad donde en caso de balanceo tiene que ser transparente para los usuarios.

Publicado por Roberto Carrancio en SQL Server, 1 comentario
Usuarios Huérfanos en SQL Server

Usuarios Huérfanos en SQL Server

Uno de los problemas más comunes cuando restauramos una base de datos de otro SQL es el de los usuarios huérfanos, vamos a ver por qué sucede y cómo solucionarlo. Antes de empezar quiero pedir perdón por el chiste malo de la foto de portada. Una vez hecho vamos a ver un poco de teoría para entender el por qué del problema y veamos como solucionarlo.

Usuarios y Logins en SQL Server

Tenemos que diferenciar los logins para acceder al servidor de los usuarios de bases de datos. Es un poco complicado, pero cuando nosotros creamos un login (inicio de sesión) sólo tendrá acceso a SQL Server sin acceder a las bases de datos. Para acceder a las bases de datos necesitaremos un usuario creado en esa base de datos y enlazado al login del servidor. 

En SQL Server tenemos dos tipos de usuarios, usuarios de windows y usuarios de SQL. Esos usuarios tienen un nombre que vemos y un identificador único con el que trabaja SQL Server. En el caso de los usuarios de windows se usa el identificador (SID) de windows (gestionado por el directorio activo o por el equipo). En el caso de los usuarios de SQL se creará un SID para el login y se usará ese mismo SID para crear un usuario en las bases de datos a las que se conceda acceso.

Usuarios huérfanos 

Sabiendo ya la diferencia entre usuarios y logins es sencillo entender el problema. Un usuario huérfano es un usuario sin login asociado. Como hemos comentado esto es muy común a la hora de mover bases de datos de un servidor a otro, pues aunque tengan los mismos usuarios lo normal es que no tengan los mismos SID. Puede pasar también en un mismo servidor, por ejemplo si borramos un login, lo volvemos a crear y no borramos los usuarios para recrearlos desde el nuevo login. 

Arreglar usuarios huérfanos

Cuando nos encontramos con este error, no podremos dar permisos al login sobre la base de datos porque aunque no tengan el mismo SID ya hay un usuario con ese nombre y los nombres de usuario deben ser únicos. La solución tampoco sería borrar el usuario para crearlo desde la ventana de logins porque perderíamos todos los permisos asignados en la base de datos y habría que volver a hacer ese trabajo. Para cuando esto pasa, SQL Server tiene una herramienta, en forma de procedimiento almacenado de sistema que localiza y corrige los usuarios huérfanos. 

Ejemplo

Como veréis en las siguientes capturas, en mi base de datos de pruebas tengo los usuarios Batman, Spiderman, Harry Potter y Superman pero en el servidor solo tengo el login Spiderman. Todos los usuarios de base de datos son huérfanos, los 3 primeros porque no existe su login padre y Superman porque, aunque existe, no están enlazados.

Localizar usuarios huérfanos

Usaremos el procedimiento almacenado con el parámetro report para localizar los usuarios huérfanos.

EXEC sp_change_users_login 'Report'

Como era de esperar el resultado del reporte nos muestra nuestros cuatro usuarios huérfanos.

Usuario y login existentes sin relación

Para corregir el problema usaremos el procedimiento almacenado con el parámetro Auto_Fix. En caso de que exista un login con el mismo nombre que nuestro usuario bastará con poner el nombre del usuario y se enlazarán.

EXEC sp_change_users_login 'Auto_fix', 'superman'

No existe el login

Cuando no exista un login con el mismo nombre podremos usar también el parámetro Auto_Fix, esta vez lo acompañaremos del nombre de usuario y la contraseña para el login que vamos a crear. 

EXEC sp_change_users_login 'Auto_fix', 'batman', NULL, 'BatContr@seña.123'

Conclusión

Hoy has aprendido qué son y por qué se producen los usuarios huérfanos y, lo más importante, como corregir este problema que es uno de los más comunes en bases de datos SQL Server. Como siempre para cualquier duda o sugerencia te emplazo dejarlo en los comentarios, mi email o nuestro twitter.

Publicado por Roberto Carrancio en SQL Server, 3 comentarios