SQL Server DB queda inutilizable durante la noche

9

Ayer, mi base de datos de SQL Server estaba bien. Hoy es casi inutilizable: se ralentiza en un factor de entre cinco y veinte, dependiendo de cuándo lo golpee.

Algunos datos se agregaron al servidor en un proceso de carga nocturna, pero nada como un volumen que debería afectar tanto a una base de datos. Alrededor de 50,000 registros de texto sin formato (sin XML u otro tipo de frippery).

El servidor fue parcheado esta mañana antes de reiniciarlo. Sin embargo, ninguno de nuestros otros servidores de bases de datos que también fueron parcheados se comportan de manera diferente.

El Monitor de recursos parece sugerir que su disco IO tiene la culpa. Se está ejecutando a casi el 100% de la capacidad en el archivo .mdf todo el tiempo, incluso cuando en realidad no hay mucho en la base de datos. El acceso a Templog.ldf también se está ejecutando bastante alto.

Nadie aquí es un DBA experto (todos somos desarrolladores con una cantidad variable de habilidades SQL) y todos estamos desconcertados por lo que sucedió. Intentamos ejecutar sp_updatestats y mover algunos de los grandes índices a diferentes discos, sin éxito.

Creo que esto debe tener algo que ver con el parche: parece demasiada coincidencia. Un colega está convencido de que es la carga de datos lo que ha provocado que el tamaño del mdf aumente hasta un punto en que los planes de ejecución se vuelven ineficientes.

¿Qué demonios ha causado esto? ¿Cómo podemos averiguarlo y qué podemos hacer para solucionarlo?

EDITAR:

Usar sp_WhoIsActiveno revela nada fuera de lo común. Registra mi propio uso de sproc y algunos comandos de un colega que actualmente está intentando mover otro índice. Probablemente eso esté retrasando la base de datos en este momento, pero antes funcionaba igual de mal.

Es la versión estándar de SQL Server 2008 R2. SELECT @@VERSIONda:

Microsoft SQL Server 2008 R2 (SP2) - 10.50.4033.0 (X64)
9 de julio de 2014 16:04:25
Copyright (c) Microsoft Corporation Standard Edition (64 bits) en Windows NT 6.1 (Build 7601: Service Pack 1) (Hypervisor )

El servidor tiene 72 GB de RAM y tres procesadores quad-core de 2 GHz.

El parche solo se aplicó a Windows. No hubo cambios aparte del parche.

Configuraciones seleccionadas:

_id     name                        value   minimum     maximum     value_in_use    description                                 is_dynamic  is_advanced
1540    min memory per query (KB)   1024    512         2147483647  1024            minimum memory per query (kBytes)           1           1
1541    query wait (s)              -1      -1          2147483647  -1              maximum time to wait for query memory (s)   1           1
1543    min server memory (MB)      0       0           2147483647  16              Minimum size of server memory (MB)          1           1
1544    max server memory (MB)      65536   16          2147483647  65536           Maximum size of server memory (MB)          1           1

ACTUALIZACIÓN: Cambiar índices y tablas a diferentes particiones de disco parece estar mejorando las cosas. Todavía estoy confundido sobre cómo podríamos haber alcanzado un punto de inflexión tan repentinamente con resultados tan drásticos.

Bob Tway
fuente
¿Puede ejecutar sp_whoisactive durante 5 minutos y capturar la salida a la tabla? Puede descargarlo desde aquí y esto mostrará cómo puede capturar la salida a la tabla
Kin Shah
Bueno, si reinició el servidor, eso significa que todos sus datos en caché se volcaron del grupo de búferes, y todos sus planes de ejecución en caché también se volcaron. Esto significa que SQL Server tendrá que acelerar ambos: cada plan de ejecución tendrá que volver a compilarse, y si las estadísticas son obsoletas, es posible que no obtenga los planes más eficientes. También significa que los datos tendrán que leerse en la memoria del disco, mientras que antes del reinicio probablemente zumbaba junto con los datos en la memoria. Esto debería ser de corta duración.
Aaron Bertrand
@AaronBertrand Ha sido así durante ocho horas. Regularmente reiniciamos el servidor para parchear y nunca antes habíamos notado algo así.
Bob Tway
1
No use la interfaz de usuario para verificar la configuración. SELECT * FROM sys.configurations;- Quieres value, value_in_usecosas como estas max server memory (MB). También SELECT @@VERSION;sería útil el número de compilación , así como si esto está en un hipervisor y si algo cambió en el host desde ayer (o desde la última vez que se reinició SQL Server).
Aaron Bertrand
2
¿Qué tipo de subsistema IO está utilizando? SAN, disco local, etc. ¿Hay alguna posibilidad de que, por coincidencia, te vaya mal? ¿También se almacenan algunos de sus DB en la misma ubicación que los archivos del sistema operativo? Y última pregunta. Parte de nuestro proceso antes de realizar una actualización del sistema operativo era tomar una instantánea de VM de antemano. Lamentablemente, la persona responsable se olvidó de cometerlo. Muy rápidamente todo el sistema se hizo más y más lento. ¿Alguna posibilidad de que esto te haya pasado?
Kenneth Fisher

Respuestas:

3

Podría suceder que una pequeña cantidad de datos alcance un cierto límite en SQL Server para forzar otro plan o algo así. Esto no es improbable. Pero el hecho de que su disco parece estar muy bajo deber me lleva a otra conclusión.

Hay 2 posibles razones básicas para su desaceleración.

  1. Actualizaste tu sistema y lo reiniciaste
  2. Cargas un montón de datos en él

Echemos un vistazo a la parte n. ° 1

Es posible que su configuración de SQL Server esté rota. Esto puede causar serios problemas con respecto a la velocidad de su servidor y el uso del disco.

Compruebe en primera instancia la configuración básica de su servidor. Esos ajustes básicos son max server memory, affinity I/O mask, affinity masky max degree of parallelism. Es posible que deba habilitar las opciones avanzadas usando show advanced options.

Aquí hay un script completo:

-- enable advanced options
EXEC sp_configure 'show advanced options',1
-- apply configuration
RECONFIGURE
-- how much memory can the sql server allocate?
EXEC sp_configure 'max server memory'
-- which cpu is used to run I/O operations
EXEC sp_configure 'affinity I/O mask'
-- which cpus can run processes?
EXEC sp_configure 'affinity mask'
-- how many threads can work on one query part?
EXEC sp_configure 'max degree of parallelism'

Compare el resultado con sus valores documentados en sus pasos de instalación. ¿Siguen siendo los mismos?

Puede tener muchas razones por las que su servidor se comporta de manera extraña. Normalmente apostaría a que tu max server memorysimplemente está equivocado. Esto hará que su servidor SQL intercambie permanentemente páginas de datos. No puede guardar todo en su memoria. Esto significa que necesita leer las páginas del disco, actualizarlo y volver a escribirlo instantáneamente. Si aparece otra actualización y usa la misma página para una actualización, no se puede leer desde la memoria. En cambio, el servidor necesita leerlo nuevamente desde el disco. Solo intercambiando ...

Otro problema puede ser una afinidad alta en disco o procesos. Si utilizó un servidor compartido (SQL Server + otros servicios) con un disco dedicado para SQL Server (que puede ser un caso raro, pero podría serlo), este podría ser su problema. Su servidor normalmente solía tener, por ejemplo, 3 cpus para procesos y uno para E / S. Los otros 12 cpus se utilizan para otros servicios. En este caso, su máscara de afinidad es incorrecta y utiliza, por ejemplo, una configuración automática. Esto significa que su servidor utiliza los 16 núcleos para procesos y E / S dinámicamente. Si tiene grandes procesos en ejecución, pueden poner una gran carga en el disco, lo que puede no manejar. Pero, de hecho, no creo que este sea tu caso. Sería más rápido (aunque sea un poco) si esto se aplicara, pero su caso es más lento.

Otro problema puede ser un grado demasiado alto de paralelismo. Lo que significa que tiene demasiados hilos inactivos en un parcial de una consulta. Esto también podría causar una gran desaceleración si el paralelismo no funciona como se esperaba. Pero esto no describirá su alta E / S en total.

Ahora echemos un vistazo a la parte n. ° 2 también

Cargas un montón de filas en tu sistema. Incluso si este es un trabajo regular, podría aumentar un límite en el que sus planes de consulta se intensifiquen. Incluso podría ocurrir que su inserción en combinación con SQL Server produzca este comportamiento.

Usted mencionó que ya intentó migrar sus índices a otro disco, lo que parece ser útil. Esto puede suceder solo por el hecho de que divide la carga en dos discos diferentes.

Puede ser que sus índices se hayan fracturado, que sus planes se hayan fracturado o que sus estadísticas estén desactualizadas.

1. verifiquemos la última actualización de estadísticas Puede hacer esto manualmente a través de la interfaz para cada elemento estadístico. Lo cual sería un dolor. O puedes probar este código:

SELECT name AS indexname,
STATS_DATE(OBJECT_ID, index_id) AS StatsUpdated
FROM sys.indexes

Esto le dará una información completa sobre cada índice (y montón) y las estadísticas detrás de ellos. Incluso si ejecuta sp_updatestats, no significa que las estadísticas se hayan actualizado. La parte en la que una actualización es bastante complicada, incluso si ejecuta sp_updatestatso incluso si auto update statisticsestá habilitada, las estadísticas no se actualizarán justo a tiempo. Aquí hay algunos puntos de borde, cuando se necesita / genera una actualización:

  • Una tabla vacía obtiene una o más filas
  • Una tabla con más de 500 filas actualiza 20% + 500 filas adicionales y luego se insertó una inserción
  • Cuando se cambiaron 500 filas en una tabla que contiene menos de 500 filas

Esto significa que sus estadísticas pueden estar desactualizadas incluso si ejecuta la actualización.

Puedes echar un vistazo a la consulta anterior. Si encuentra algunas estadísticas bastante antiguas en algunas tablas, puede ejecutar una actualización estadística manual para esta tabla:

UPDATE STATISTICS dbo.YourBadTable WITH FULLSCAN

Después de eso, es posible que desee darle a su servidor una patada en el culo para tirar todos los planes antiguos.

DBCC FREEPROCCACHE 

Si solo desea limpiar todos los cachés, puede ejecutar esto en su lugar:

DBCC FREESYSTEMCACHE ('ALL')

Esto limpiará todos los cachés, no solo el caché del plan. Normalmente advierto que use esto en un servidor de producción en la fase de producción. Pero como su servidor no funciona actualmente, no puede dañarlos demasiado. Puede ralentizarse durante algunos segundos, tal vez 1-2 minutos, ya que necesita reconstruir todos los cachés, pero después de eso debe correr con los planes correctos.

Otra razón puede ser índices totalmente fragmentados. Esto se puede verificar en todo el servidor utilizando esta declaración:

SELECT * 
FROM sys.dm_db_index_physical_stats (NULL, NULL, NULL, NULL, NULL)

Si la fragmentación es muy alta, es posible que deba reorganizarla (fragmentación <20%) o reconstruirla por completo (> 20%). Esto puede ejercer más presión sobre su disco y causar problemas. Por otro lado, si los índices son tan malos, probablemente ayudaría al final más de lo que perjudica.

Además de estas dos razones, todavía puede haber un tercer problema.

Es posible que su servidor esté configurado probablemente, no ha cambiado ningún código en este momento, solo ha agregado algunas filas. Todas las estadísticas se actualizan y todas las cachés se reconstruyen. Todos sus índices se reorganizan de la forma en que los necesita, pero aún así, nada funciona. Es posible que haya alcanzado el límite de memoria disponible en sus procesos. Quizás necesites más. Simplemente puede verificar si hay algún proceso que intente obtener más memoria de la que tiene.

Puede verificar esto usando este comando:

SELECT * FROM sys.dm_exec_query_memory_grants

Le proporcionará una lista de todas las sesiones que consumen memoria. Puede haber alguna consulta que todavía está esperando obtener memoria. Esas consultas se pueden filtrar fácilmente. Todas las sesiones donde granted_memory_kb IS NULL. Estas son sesiones que solicitaron memoria pero no la obtienen. Otra cosa puede ser una memoria garantizada que puede ser demasiado baja. Puedes comparar las columnas requested_memory_kbcon granted_memory_kb. La cantidad solicitada muestra la cantidad de memoria que el proceso necesita para ejecutarse de manera óptima, mientras que si se otorga, muestra la memoria habilitada para el proceso. Si un proceso necesita 2 GB para ejecutarse pero solo obtiene 2 MB ... puede obtenerlo usted mismo. ;-)

Otra forma es verificar RESSOURCE_SEMAPHORE:

SELECT * FROM sys.dm_exec_query_resource_semaphore

Puedes echar un vistazo a la waiter_county la grantee_count. Si el camarero está por encima de 0, tiene presión en su memoria, lo que puede causar un intercambio y puede causar la presión del disco que ve en el perfmon.

Iónico
fuente
0

Además de las posibles fallas de la unidad, verifique el estado de su subsistema RAID. Vimos algo similar y resultó que la batería del controlador RAID falló, por lo que no había caché de escritura disponible: todas las escrituras tenían que ir directamente al disco. Una nota al margen: podríamos sentir que el sistema se detiene mientras RDC 'entra en él.

William Jens
fuente