Sqlserver
 sql >> Base de données >  >> RDS >> Sqlserver

Comment détecter et empêcher une croissance inattendue de la base de données SQL Server TempDB

Chaque instance SQL Server contient la base de données système SQL Server appelée TempDB. C'est typique pour toutes les connexions à la base de données, et presque toutes les requêtes utilisent la base de données TempDB. C'est comme un cœur pour l'instance SQL Server. Pratiquement, nous ne pouvons pas travailler sans la base de données TempDB.

Faisons un bref résumé des opérations dans lesquelles SQL Server utilise TempDB.

  • Trier par et Grouper par clause
  • Création d'index et reconstruction d'index en ligne
  • Le stockage des tables temporaires et des variables de table se trouve dans la base de données TempDB.
  • Isolation d'instantané et isolation d'instantané validé en lecture
  • Commandes DBCC
  • Le hachage joint les curseurs statiques, les transactions de longue durée.
  • Requêtes XML
  • Objets internes créés par le moteur de base de données SQL Server.
  • Magasins de versions
  • Plusieurs jeux d'enregistrements actifs (MARS)

Vous pouvez en savoir plus sur TempDB dans cet article.

SQL Server recrée cette base de données TempDB au redémarrage du service du moteur de base de données. Ce redémarrage peut être dû au redémarrage automatique ou manuel du service SQL. Nous pouvons interroger sys.databases pour afficher la date de création de TempDB qui est également une heure de démarrage du service de base de données :

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

Configurations et meilleures pratiques de la base de données TempDB SQL Server

Parfois, nous remarquons une croissance inattendue de la base de données TempDB. La première étape pour éviter cela est de le configurer selon les meilleures pratiques. Dans cette section, examinons la configuration de TempDB dans différentes versions de SQL Server.

Configurer TempDB pour plusieurs fichiers de données avec une croissance uniforme

Conformément aux meilleures pratiques, nous devrions avoir plusieurs fichiers de données avec une croissance uniforme de tous les fichiers. Le nombre de fichiers dépend des processeurs logiques.

Processeurs

Nombre de fichiers de données TempDB

Processeurs logiques inférieurs ou égaux à huit

Huit

Processeurs logiques supérieurs à huit

Commencez avec huit fichiers de données.

Augmentez les fichiers de données en multiples de quatre et surveillez les compteurs de performance pour les conflits TempDB.

Pour les versions de SQL Server antérieures à 2016, nous n'avons pas de configuration disponible pendant le processus d'installation.

Par défaut, il crée un seul fichier de données et journal avec les configurations suivantes :

Fichier primaire TempDB

Agrandir automatiquement le fichier de données de dix pour cent (jusqu'à ce que le disque soit plein)

Fichier journal TempDB

Agrandir automatiquement le fichier de données de 10 % (jusqu'à ce que le disque soit plein ou que la taille maximale du fichier journal atteigne 2 To)

Configuration de la base de données SQL Server 2014 TempDB SQL Server

SQL Server 2016 fournit des améliorations pour la configuration de TempDB pendant le processus d'installation conformément à la meilleure pratique :

TempDB Fichiers primaires et secondaires

Croissance automatique de 64 Mo (jusqu'à ce que le disque soit plein)

Fichier journal TempDB

Croissance automatique de 64 Mo (jusqu'à ce que le disque soit plein ou que la taille maximale du fichier journal atteigne 2 To)

Configuration de SQL Server 2016 et versions ultérieures

Base de données SQL Server à croissance automatique inégale TempDB

SQL Server utilise une méthode circulaire pour remplir plusieurs fichiers de données s'ils n'ont pas la même taille. Parfois, nous voyons qu'un fichier devient énorme, mais d'autres fichiers restent une croissance minimale. En cas de fichiers inégaux, SQL Server utilise le fichier le plus volumineux pour la plupart des requêtes, et il continuerait de croître :

  1. Utilisez la même croissance automatique des fichiers TempDB (comme indiqué au point précédent).
  2. Activez l'indicateur de trace 1117 pour développer tous les fichiers de données ensemble dans une base de données.

Le deuxième point est corrigé automatiquement dans SQL Server 2016, mais vous devez l'activer dans les versions antérieures. Nous n'avons pas besoin de cet indicateur de trace dans SQL Server 2016 et versions ultérieures.

Scénarios de croissance TempDB

Dans cette section, nous verrons quelques scénarios de croissance TempDB de la base de données SQL Server. Dans mon instance SQL, j'ai huit fichiers de données avec la configuration suivante :

Maintenant, exécutez la requête suivante pour créer une table temporaire et effectuer l'insertion de données. L'emplacement de stockage de la table temporaire est la base de données TempDB. Cette requête utilise un opérateur CROSS JOIN avec plusieurs colonnes et trie davantage les résultats à l'aide de la clause ORDER BY.

Remarque : N'exécutez pas cette requête dans le système de production; Je l'utilise uniquement à des fins de démonstration.

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;

Cette requête prendra beaucoup de temps et pourrait également entraîner une utilisation élevée du processeur dans votre système. Pendant que la requête est en cours d'exécution, ouvrez une autre fenêtre de requête et utilisez le DMV sys.dm_db_task_space_usage pour obtenir des informations sur activité d'allocation et de désallocation de pages par la tâche. Nous joignons ce DMV avec d'autres DMV pour obtenir les informations requises pour la base de données SQL Server TempDB :

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;
Dans la sortie, nous voyons le nombre de pages d'objets internes et leurs tailles (kbytes_used_internal) pour l'ID de session 55. Optimiseur de requête SQL Server exécutant cette requête dans un modèle parallèle; par conséquent, nous pouvons voir plusieurs ID de session 71 dans la sortie :

Vous pouvez également consulter le plan d'exécution estimé et, comme indiqué ci-dessous, nous obtenons deux opérateurs coûteux :

  • Parallélisme :47,3 %
  • Tri :52,3 %

Dans l'opérateur de tri, nous pouvons voir un coût d'opérateur estimé élevé de 138 576,5 :

La requête suivante utilise DMV sys.dm_db_file_space_usage et le joint à sys.master_files pour vérifier le nombre de pages d'extension allouées et non allouées dans la base de données SQL Server TempDB pendant l'exécution de la requête :

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

Nous pouvons surveiller l'exécution de la requête, son utilisation dans la base de données TempDB et, si nécessaire, tuer le processus pour libérer l'espace immédiatement. Nous devrions également optimiser la requête provoquant une croissance massive de TempDB.

Surveiller l'utilisation de TempDB de la base de données SQL Server à l'aide d'événements étendus

Les événements étendus sont utiles pour la surveillance de la base de données TempDB. Nous pouvons ajouter les événements étendus suivants à l'aide de la requête :

  • database_file_size_change
  • databases_log_file_used_size_changed

Créer un événement étendu

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

Démarrer une session d'événement prolongée

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

Maintenant, exécutez votre charge de travail pour utiliser la base de données TempDB et développer les fichiers de données. Les événements étendus capturent la croissance des fichiers de données et la requête à l'origine de cette croissance.

Vous pouvez soit afficher le fichier de session d'événement étendu en mode SSMS GUI, soit utiliser la requête suivante pour surveiller la croissance de TempDB.

Surveiller la croissance de TempDB

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;

Isolation d'instantané

Vous pouvez utiliser l'isolement d'instantané pour vos requêtes. Dans ce modèle d'isolation, SQL Server stocke les versions de ligne mises à jour de chaque transaction dans TempDB. En cas de transaction importante ou de longue durée, vous pouvez voir une énorme base de données TempDB.

Vous pouvez exécuter la transaction avec la commande SET et spécifier l'isolation d'instantané :

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

Vous pouvez également interroger sys.databases vue système pour vérifier si une base de données utilisateur a une isolation d'instantané.

Requête pour activer l'isolement d'instantané sur la base de données AdventureWorks

ALTER DATABASE AdventureWorks
SET ALLOW_SNAPSHOT_ISOLATION ON
GO

Requête pour vérifier la base de données utilisateur avec isolement d'instantané

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

Dans la capture d'écran suivante, vous pouvez voir que la base de données AdventureWorks dispose d'un isolement d'instantané. La base de données TempDB a également une isolation d'instantané, mais dans la requête, nous avons ignoré database_id inférieur à 4 :

Nous pouvons utiliser DMV sys.dm_db_file_space_usage pour surveiller le magasin de versions dans 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;

Ici, nous pouvons voir que la taille du magasin de versions est de 67968 Ko. Pour une transaction importante ou de longue durée, vous pouvez voir une énorme taille TempDB de base de données SQL Server en raison de ce magasin de versions :

Un autre cas pouvant entraîner une taille énorme du magasin de versions est Toujours sur le réplica secondaire en lecture seule. Si vous exécutez une requête sur la base de données secondaire, elle utilise automatiquement le niveau d'isolement d'instantané. Comme vous le savez, le niveau d'isolement d'instantané copie la version de ligne dans TempDB.

Vous devez surveiller les compteurs de performances suivants :

  • SQLServer : Transactions\Durée d'exécution de la transaction la plus longue – Il capture la transaction active la plus longue.
  • SQLServer : Transactions\Taille du magasin de versions (Ko) – Il capture la taille actuelle de tous les magasins de versions dans TempDB.
  • SQLServer :Transactions\Taux de nettoyage de version (Ko/s ) – Vous pouvez utiliser ce compteur pour afficher le taux de nettoyage de version dans TempDB
  • SQLServer :Transactions\Taux de génération de version (Ko/s) – Vous pouvez capturer le taux de capture du magasin de versions à l'aide de ce compteur.

Vous devez également surveiller la croissance de TempDB pour la gestion des versions dans Always sur la base de données secondaire. Tuez les sessions de longue durée afin qu'il puisse effacer le versioning et récupérer de l'espace dans la base de données TempDB.

Conclusion

Dans cet article, nous avons découvert la meilleure pratique de la base de données TempDB de la base de données SQL Server et différentes méthodes pour détecter et empêcher une croissance inattendue. Vous devez surveiller régulièrement TempDB et configurer différentes alertes pour être proactif.

  • Surveillance de la taille de TempDB
  • Surveillance de l'espace disque
  • Transactions de longue durée