sql >> Base de Datos >  >> RDS >> Sqlserver

Cómo detectar y prevenir el crecimiento inesperado de la base de datos TempDB de SQL Server

Cada instancia de SQL Server contiene la base de datos del sistema SQL Server llamada TempDB. Es típico para todas las conexiones de base de datos, y casi todas las consultas utilizan la base de datos TempDB. Es como un corazón para la instancia de SQL Server. Prácticamente, no podemos trabajar sin la base de datos TempDB.

Veamos un breve resumen de las operaciones en las que SQL Server usa TempDB.

  • Cláusula Ordenar por y Agrupar por
  • Creación de índices y reconstrucción de índices en línea
  • El almacenamiento de tablas temporales y variables de tabla se encuentra en la base de datos TempDB.
  • Aislamiento de instantáneas y aislamiento de instantáneas de lectura confirmada
  • Comandos DBCC
  • Hash une cursores estáticos, transacciones de ejecución prolongada.
  • Consultas XML
  • Objetos internos creados por el motor de base de datos de SQL Server.
  • Almacenes de versiones
  • Múltiples conjuntos de registros activos (MARS)

Puede leer más sobre TempDB en este artículo.

SQL Server recrea esta base de datos TempDB en el reinicio del servicio del motor de la base de datos. Este reinicio puede deberse al reinicio automático o manual de SQL Service. Podemos consultar sys.databases para ver la fecha de creación de TempDB que también es una hora de inicio del servicio de la base de datos:

SELECT create_date AS 'SQL Service Startup Time'
FROM sys.databases
WHERE name = 'tempdb';

Configuraciones y mejores prácticas de la base de datos TempDB SQL Server

A veces, notamos un crecimiento inesperado de la base de datos TempDB. El primer paso para evitar esto es configurarlo según las mejores prácticas. En esta sección, veamos la configuración de TempDB en diferentes versiones de SQL Server.

Configure TempDB para múltiples archivos de DATOS con un crecimiento uniforme

Según las mejores prácticas, deberíamos tener múltiples archivos de datos con un crecimiento uniforme de todos los archivos. El número de archivos depende de los procesadores lógicos.

Procesadores

Número de archivos de datos TempDB

Procesadores lógicos menores o iguales a ocho

Ocho

Procesadores lógicos mayores de ocho

Comience con ocho archivos de datos.

Aumente los archivos de datos en múltiplos de cuatro y supervise los contadores de rendimiento para la contención de TempDB.

Para versiones de SQL Server anteriores a 2016, no tenemos configuración disponible durante el proceso de instalación.

De forma predeterminada, crea solo un archivo de datos y registro con las siguientes configuraciones:

Archivo principal de TempDB

Archivo de datos de crecimiento automático en un diez por ciento (hasta que el disco esté lleno)

Archivo de registro de TempDB

Aumentar automáticamente el archivo de datos en un diez por ciento (hasta que el disco esté lleno o el tamaño máximo del archivo de registro llegue a 2 TB)

Configuración de la base de datos SQL Server 2014 TempDB SQL Server

SQL Server 2016 proporciona mejoras para la configuración de TempDB durante el proceso de instalación según las mejores prácticas:

TempDB Archivos primarios y secundarios

Crecimiento automático de 64 MB (hasta que el disco esté lleno)

Archivo de registro de TempDB

Crecimiento automático de 64 MB (hasta que el disco esté lleno o el tamaño máximo del archivo de registro llegue a 2 TB)

Configuración de TempDB de SQL Server 2016 en adelante

TempDB de la base de datos SQL Server de crecimiento automático desigual

SQL Server utiliza un método de rotación para llenar varios archivos de datos si no tienen el mismo tamaño. A veces, vemos que un archivo crece enormemente, pero otros archivos siguen creciendo al mínimo. En el caso de archivos irregulares, SQL Server usa el archivo más grande para la mayoría de las consultas y seguirá creciendo:

  1. Utilice el mismo crecimiento automático de los archivos TempDB (como se explicó en el punto anterior).
  2. Habilite la marca de seguimiento 1117 para hacer crecer todos los archivos de datos en una base de datos.

El segundo punto se corrige automáticamente en SQL Server 2016 en adelante; sin embargo, debe habilitarlo en versiones anteriores. No requerimos esta marca de seguimiento en SQL Server 2016 y versiones posteriores.

Escenarios de crecimiento de TempDB

En esta sección, veremos algunos escenarios para el crecimiento de TempDB de la base de datos de SQL Server. En mi instancia de SQL, tengo ocho archivos de datos con la siguiente configuración:

Ahora, ejecute la siguiente consulta para crear una tabla temporal y realizar la inserción de datos. La ubicación de almacenamiento de la tabla temporal es la base de datos TempDB. Esta consulta usa un operador CROSS JOIN con múltiples columnas y ordena aún más los resultados usando la cláusula ORDER BY.

Nota: No ejecute esta consulta en el sistema de producción; Lo estoy usando solo con fines de demostración.

SELECT *
FROM sys.configurations
CROSS JOIN sys.configurations SCA
CROSS JOIN sys.configurations SCB
CROSS JOIN sys.configurations SCC
CROSS JOIN sys.configurations SCD
CROSS JOIN sys.configurations SCE
CROSS JOIN sys.configurations SCF
CROSS JOIN sys.configurations SCG
CROSS JOIN sys.configurations SCH
ORDER BY SCA.name,
SCA.value,
SCC.value_in_use DESC;

Esta consulta llevará mucho tiempo y podría resultar en un alto uso de la CPU también en su sistema. Mientras se ejecuta la consulta, abra otra ventana de consulta y use el DMV sys.dm_db_task_space_usage para obtener información de actividad de asignación y desasignación de páginas por tarea. Unimos este DMV con otros DMV para obtener la información requerida para la base de datos TempDB de SQL Server:

SELECT s.session_id, dbu.database_id
, dbu.internal_objects_alloc_page_count, dbu.internal_objects_dealloc_page_count
, (dbu.internal_objects_alloc_page_count - dbu.internal_objects_dealloc_page_count) * 8192 / 1024 kbytes_used_internal
, r.total_elapsed_time
FROM sys.dm_Exec_requests r
INNER JOIN sys.dm_exec_sessions s ON r.session_id = s.session_id
LEFT JOIN sys.dm_db_task_space_usage dbu ON dbu.session_id = r.session_id
AND dbu.request_id = r.request_id
WHERE internal_objects_alloc_page_count > 0
ORDER BY kbytes_used_internal DESC;
En el resultado, vemos los recuentos de páginas de objetos internos y sus tamaños (kbytes_used_internal) para el ID de sesión 55. El optimizador de consultas de SQL Server ejecuta esta consulta en un modelo paralelo; por lo tanto, podemos ver múltiples ID de sesión 71 en la salida:

También puede ver el plan de ejecución estimado y, como se muestra a continuación, tenemos dos operadores costosos:

  • Paralelismo:47,3 %
  • Tipo:52,3 %

En el operador de clasificación, podemos ver un alto costo estimado del operador 138,576.5:

La siguiente consulta utiliza DMV sys.dm_db_file_space_usage y lo une con sys.master_files para comprobar los recuentos de páginas de extensiones asignadas y no asignadas en la base de datos TempDB de SQL Server mientras se ejecuta la consulta:

select mf.physical_name, mf.size as entire_file_page_count,
dfsu.unallocated_extent_page_count,
dfsu.user_object_reserved_page_count,
dfsu.internal_object_reserved_page_count,
dfsu.mixed_extent_page_count
from sys.dm_db_file_space_usage dfsu
join sys.master_files as mf
on mf.database_id = dfsu.database_id
and mf.file_id = dfsu.file_id

Podemos monitorear la ejecución de la consulta, su uso en la base de datos TempDB y, si es necesario, eliminar el proceso para liberar el espacio de inmediato. También deberíamos optimizar la consulta que causa un crecimiento masivo de TempDB.

Supervise el uso de TempDB de la base de datos de SQL Server mediante eventos extendidos

Los eventos extendidos son útiles para el monitoreo de la base de datos TempDB. Podemos agregar los siguientes eventos extendidos usando la consulta:

  • cambio_de_tamaño_de_archivo_de_base_de_datos
  • databases_log_file_used_size_changed

Crear evento extendido

CREATE EVENT SESSION [TempDB Usage] ON SERVER
ADD EVENT sqlserver.database_file_size_change(

ACTION(sqlserver.client_hostname,sqlserver.database_id,sqlserver.session_id,sqlserver.sql_text)),
ADD EVENT sqlserver.databases_log_file_used_size_changed(

ACTION(sqlserver.client_hostname,sqlserver.database_id,sqlserver.session_id,sqlserver.sql_text))
ADD TARGET package0.event_file(SET filename=N'TempDBUsage',max_rollover_files=(0))
WITH (STARTUP_STATE=OFF)
GO

Iniciar sesión de evento extendida

ALTER EVENT SESSION [TempDBTest] ON SERVER STATE = START;

Ahora, ejecute su carga de trabajo para usar la base de datos TempDB y hacer crecer los archivos de datos. Los eventos extendidos capturan el crecimiento del archivo de datos y la consulta que causó este crecimiento.

Puede ver el archivo de sesión de eventos extendidos en el modo GUI de SSMS o usar la siguiente consulta para monitorear el crecimiento de TempDB.

Supervisión del crecimiento de la base de datos temporal

SELECT [eventdata].[event_data].[value]('(event/action[@name="session_id"]/value)[1]', 'INT') AS [SessionID],
[eventdata].[event_data].[value]('(event/action[@name="client_hostname"]/value)[1]', 'VARCHAR(100)') AS [ClientHostName],
DB_NAME([eventdata].[event_data].[value]('(event/action[@name="database_id"]/value)[1]', 'BIGINT')) AS [GrowthDB],
[eventdata].[event_data].[value]('(event/data[@name="file_name"]/value)[1]', 'VARCHAR(200)') AS [GrowthFile],
[eventdata].[event_data].[value]('(event/data[@name="file_type"]/text)[1]', 'VARCHAR(200)') AS [DBFileType],
[eventdata].[event_data].[value]('(event/@name)[1]', 'VARCHAR(MAX)') AS [EventName],
[eventdata].[event_data].[value]('(event/data[@name="size_change_kb"]/value)[1]', 'BIGINT') AS [SizeChangedKb],
[eventdata].[event_data].[value]('(event/data[@name="total_size_kb"]/value)[1]', 'BIGINT') AS [TotalSizeKb],
[eventdata].[event_data].[value]('(event/data[@name="duration"]/value)[1]', 'BIGINT') AS [DurationInMS],
[eventdata].[event_data].[value]('(event/@timestamp)[1]', 'VARCHAR(MAX)') AS [GrowthTime],
[eventdata].[event_data].[value]('(event/action[@name="sql_text"]/value)[1]', 'VARCHAR(MAX)') AS [QueryText]
FROM
(
SELECT CAST([event_data] AS XML) AS [TargetData]
FROM [sys].[fn_xe_file_target_read_file]('C:\TEMP\TempDBusage*.xel', NULL, NULL, NULL)
) AS [eventdata]([event_data])
WHERE [eventdata].[event_data].[value]('(event/@name)[1]', 'VARCHAR(100)') = 'database_file_size_change'
OR [eventdata].[event_data].[value]('(event/@name)[1]', 'VARCHAR(100)') = 'databases_log_file_used_size_changed'
AND [eventdata].[event_data].[value]('(event/@name)[1]', 'VARCHAR(MAX)') <> 'databases_log_file_used_size_changed'
ORDER BY [GrowthTime] ASC;

Aislamiento de instantáneas

Puede usar el aislamiento de instantáneas para sus consultas. En este modelo de aislamiento, SQL Server almacena las versiones de fila actualizadas de cada transacción en TempDB. En el caso de una transacción grande o de larga duración, puede ver una enorme base de datos TempDB.

Puede ejecutar la transacción con el comando SET y especificar el aislamiento de instantánea:

SET TRANSACTION ISOLATION LEVEL SNAPSHOT;
BEGIN TRAN;
UPDATE [AdventureWorks].[Person].[Person]
SET
[Title] = 'Mr.';
COMMIT TRAN;

También puede consultar sys.databases vista del sistema para verificar si alguna base de datos de usuario tiene aislamiento de instantáneas.

Consulta para habilitar el aislamiento de instantáneas en la base de datos AdventureWorks

ALTER DATABASE AdventureWorks
SET ALLOW_SNAPSHOT_ISOLATION ON
GO

Consulta para verificar la base de datos del usuario con aislamiento de instantáneas

SELECT *
FROM sys.databases
WHERE(snapshot_isolation_state = 1
OR is_read_committed_snapshot_on = 1)
AND database_id > 4;

En la siguiente captura de pantalla, puede ver que la base de datos AdventureWorks tiene aislamiento de instantáneas. La base de datos TempDB también tiene aislamiento de instantáneas, pero en la consulta hemos omitido database_id menor que 4:

Podemos usar DMV sys.dm_db_file_space_usage para monitorear el almacén de versiones en TempDB:

SELECT GETDATE() AS runtime,
SUM(user_object_reserved_page_count) * 8 AS usr_obj_kb,
SUM(internal_object_reserved_page_count) * 8 AS internal_obj_kb,
SUM(version_store_reserved_page_count) * 8 AS version_store_kb,
SUM(unallocated_extent_page_count) * 8 AS freespace_kb,
SUM(mixed_extent_page_count) * 8 AS mixedextent_kb
FROM sys.dm_db_file_space_usage;

Aquí, podemos ver que el tamaño de la tienda de versiones es de 67968 KB. Para una transacción grande o de larga ejecución, puede ver un enorme tamaño de TempDB de la base de datos de SQL Server debido a este almacén de versiones:

Otro caso que podría causar un gran tamaño del almacén de versiones es Siempre en una réplica secundaria de solo lectura. Si ejecuta cualquier consulta en la base de datos secundaria, automáticamente utiliza el nivel de aislamiento de instantánea. Como sabe, el nivel de aislamiento de la instantánea copia la versión de la fila en TempDB.

Debe monitorear los siguientes contadores perfmon:

  • SQLServer:Transacciones\Tiempo de ejecución de transacción más largo – Captura la transacción activa más extendida.
  • SQLServer:Transacciones\Versión Tamaño del almacén (KB) – Captura el tamaño actual de todas las versiones almacenadas en TempDB.
  • SQLServer:Transacciones\Velocidad de limpieza de versión (KB/s ) – Puede usar este contador para mostrar la tasa de limpieza de versiones en TempDB
  • SQLServer:Transacciones\Velocidad de generación de versiones (KB/s) – Puede capturar la tasa de captura de la tienda de versiones usando este contador.

También debe supervisar el crecimiento de TempDB para el control de versiones en Siempre en la base de datos secundaria. Elimine las sesiones de ejecución prolongada para que pueda borrar el control de versiones y recuperar espacio en la base de datos TempDB.

Conclusión

En este artículo, aprendimos sobre las mejores prácticas de la base de datos TempDB de la base de datos de SQL Server y los diferentes métodos para detectar y prevenir el crecimiento inesperado. Debe monitorear TempDB regularmente y configurar diferentes alertas para ser proactivo.

  • Supervisión del tamaño de TempDB
  • Supervisión del espacio de conducción
  • Transacciones de larga duración