SQL Server DB devient inutilisable du jour au lendemain

9

Hier, ma base de données SQL Server allait bien. Aujourd'hui, il est presque inutilisable - il est ralenti d'un facteur compris entre cinq et vingt, selon le moment où je l'ai frappé.

Certaines données ont été ajoutées au serveur lors d'un processus de chargement de nuit, mais rien de tel qu'un volume qui devrait avoir un impact important sur une base de données. Environ 50 000 enregistrements en texte brut (pas de XML ou autre frippery).

Le serveur a été corrigé ce matin avant de le redémarrer. Cependant, aucun de nos autres serveurs de base de données qui ont également été corrigés ne se comporte différemment.

Le moniteur de ressources semble suggérer que son E / S de disque est en cause. Il fonctionne à près de 100% de sa capacité sur le fichier .mdf tout le temps, même lorsqu'il ne se passe pas grand-chose dans la base de données. L'accès à Templog.ldf est également assez élevé.

Personne ici n'est un expert DBA (nous sommes tous des développeurs avec une quantité variable de compétences SQL) et nous sommes tous déconcertés par ce qui s'est passé. Nous avons essayé d'exécuter sp_updatestats et de déplacer certains des gros index vers différents disques, en vain.

Je pense que cela doit avoir quelque chose à voir avec le patch - il semble trop d'une co-incidence. Un collègue est convaincu que c'est la charge de données qui a provoqué l'augmentation de la taille du mdf à un point tel que les plans d'exécution sont devenus inefficaces.

Qu'est-ce qui a causé ça? Comment pouvons-nous le savoir et que pouvons-nous faire pour y remédier?

ÉDITER:

L'utilisation sp_WhoIsActivene révèle rien d'extraordinaire. Il enregistre ma propre utilisation du sproc et de certaines commandes d'un collègue qui essaie actuellement de déplacer un autre index. Cela retarde probablement la DB en ce moment, mais elle fonctionnait tout aussi mal auparavant.

Il s'agit de la version standard de SQL Server 2008 R2. SELECT @@VERSIONdonne:

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

Le serveur dispose de 72 Go de RAM et de trois processeurs quad-core 2 GHz.

Le patch n'a été appliqué qu'à Windows. Il n'y a eu aucun changement autre que le patch.

Paramètres sélectionnés:

_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

MISE À JOUR: Le déplacement des index et des tables vers différentes partitions de disque semble améliorer les choses. Je suis toujours confus sur la façon dont nous aurions pu atteindre un point de basculement si soudainement avec des résultats aussi drastiques.

Bob Tway
la source
Pouvez-vous exécuter sp_whoisactive pendant 5 minutes et capturer la sortie dans la table. Vous pouvez le télécharger à partir d' ici et cela montrera comment vous pouvez capturer la sortie vers la table
Kin Shah
Eh bien, si vous redémarrez le serveur, cela signifie que toutes vos données mises en cache ont été vidées du pool de tampons, et tous vos plans d'exécution mis en cache ont également été vidés. Cela signifie que SQL Server devra augmenter les deux - chaque plan d'exécution devra être recompilé, et si les statistiques sont périmées, vous n'obtiendrez peut-être pas les plans les plus efficaces. Cela signifie également que les données devront être lues en mémoire à partir du disque, alors qu'avant le redémarrage, elles fredonnaient probablement avec les données en mémoire. Cela devrait être de courte durée.
Aaron Bertrand
@AaronBertrand Ça fait huit heures comme ça. Nous redémarrons régulièrement le serveur pour les correctifs et nous n'avons jamais rien remarqué de tel auparavant.
Bob Tway
1
N'utilisez pas l'interface utilisateur pour vérifier les paramètres de configuration. SELECT * FROM sys.configurations;- vous voulez value, value_in_usepour des choses comme max server memory (MB). Le numéro de build dans SELECT @@VERSION;serait également utile, ainsi que s'il s'agit d'un hyperviseur et si quelque chose a changé sur l'hôte depuis hier (ou depuis le dernier redémarrage de SQL Server).
Aaron Bertrand
2
Quel type de sous-système d'E / S utilisez-vous? SAN, disque local, etc.? Y a-t-il une chance que votre route tourne mal par hasard? Certains de vos DB sont-ils également stockés au même emplacement que tous les fichiers du système d'exploitation? Et dernière question. Une partie de notre processus avant de faire une mise à niveau du système d'exploitation consistait à prendre un instantané de machine virtuelle au préalable. Malheureusement, le responsable a oublié de le commettre. Très rapidement, l'ensemble du système est devenu de plus en plus lent. Une chance que cela vous soit arrivé?
Kenneth Fisher

Réponses:

3

Il peut arriver qu'une petite quantité de données atteigne une certaine limite dans SQL Server pour forcer un autre plan ou quelque chose comme ça. Ce n'est pas improbable. Mais le fait que votre disque semble être lourdement contraint m'amène à une autre conclusion.

Il y a 2 raisons possibles à votre ralentissement.

  1. Vous avez mis à niveau votre système et l'avez redémarré
  2. Vous y chargez un tas de données

Jetons un coup d'œil à la partie n ° 1

Il se peut que votre configuration SQL Server soit rompue. Cela peut entraîner de graves problèmes concernant la vitesse de votre serveur et l'utilisation du disque.

Veuillez vérifier en premier lieu les paramètres de base de votre serveur. Ces réglages de base sont max server memory, affinity I/O mask, affinity masket max degree of parallelism. Vous devrez peut-être activer les options avancées à l'aide de show advanced options.

Voici un script complet:

-- 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'

Comparez le résultat avec vos valeurs documentées dans vos étapes d'installation. Sont-ils toujours les mêmes?

Il peut y avoir plusieurs raisons pour lesquelles votre serveur se comporte si étrangement. Je parierais normalement que vous vous max server memorytrompez. Cela entraînera l'échange de pages de données de votre serveur SQL en permanence. Il ne peut pas tout garder en mémoire. Cela signifie qu'il doit lire les pages du disque, le mettre à jour, le réécrire instantanément. Si une autre mise à jour arrive et utilise la même page pour une mise à jour, elle ne peut pas être lue dans la mémoire. Au lieu de cela, le serveur doit le relire à partir du disque. Échange juste ...

Un autre problème peut être lié à une affinité élevée sur le disque ou les processus. Si vous avez utilisé un serveur partagé (SQL Server + autres services) avec un disque dédié pour SQL Server (ce qui peut être un cas rare, mais cela pourrait l'être), cela pourrait être votre problème. Votre serveur avait normalement par exemple 3 processeurs pour les processus et un pour les E / S. Les 12 autres CPU sont utilisés pour d'autres services. Dans ce cas, votre masque d'affinité est incorrect et utilise par exemple une configuration automatique. Cela signifie que votre serveur utilise les 16 cœurs pour les processus et les E / S de manière dynamique. Si vous avez d'énormes processus en cours d'exécution, ils peuvent mettre une énorme charge sur le disque, qu'il ne peut pas gérer. Mais en fait, je ne pense pas que ce soit votre cas. Ce serait plus rapide (même si c'est juste un peu) si cela s'appliquait, mais votre cas est un ralentissement.

Un autre problème peut être un degré de parallélisme trop élevé. Ce qui signifie que vous avez trop de threads au ralenti sur une partie d'une requête. Cela pourrait également provoquer un énorme ralentissement si le parallélisme ne fonctionne pas comme prévu. Mais cela ne décrira pas votre total d'E / S élevées.

Jetons maintenant un œil à la partie n ° 2 également

Vous chargez un tas de lignes dans votre système. Même s'il s'agit d'un travail normal, cela pourrait augmenter la limite dans laquelle vos plans de requête s'intensifient. Il se peut même que votre insertion en combinaison avec SQL Server produise ce comportement.

Vous avez mentionné que vous avez déjà essayé de migrer vos index vers un autre disque, ce qui semble vous aider. Cela peut être dû au fait que vous divisez la charge sur deux disques différents.

Il se peut que vos indices aient été fracturés, que vos plans aient été fracturés ou que vos statistiques soient juste dépassées.

1. permet de vérifier les dernières mises à jour des statistiques Vous pouvez le faire manuellement via l'interface pour chaque élément statistique unique. Ce serait une douleur. Ou vous pouvez essayer ce code:

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

Cela vous donnera une information complète sur chaque index (et tas) et les statistiques derrière eux. Même si vous l'exécutez, sp_updatestatscela ne signifie pas que les statistiques ont été mises à jour. La partie lorsqu'une mise à jour est assez délicate, même si vous exécutez sp_updatestatsou même si elle auto update statisticsest activée, les statistiques ne seront pas mises à jour juste à temps. Voici quelques points marginaux, lorsqu'une mise à jour est nécessaire / générée:

  • Une table vide obtient une ou plusieurs lignes
  • Un tableau avec plus de 500 lignes met à jour 20% + 500 lignes supplémentaires et une insertion s'est produite par la suite
  • Lorsque 500 lignes ont été modifiées dans une table contenant moins de 500 lignes

Cela signifie que vos statistiques peuvent être obsolètes même si vous exécutez la mise à jour.

Vous pouvez jeter un œil à la requête ci-dessus. Si vous trouvez des statistiques assez anciennes dans certains tableaux, vous souhaiterez peut-être exécuter une mise à jour manuelle des statistiques pour ce tableau:

UPDATE STATISTICS dbo.YourBadTable WITH FULLSCAN

Après cela, vous voudrez peut-être donner un coup de pied à votre serveur pour jeter tous les anciens plans.

DBCC FREEPROCCACHE 

Si vous souhaitez simplement nettoyer tous les caches, vous pouvez exécuter ceci à la place:

DBCC FREESYSTEMCACHE ('ALL')

Cela nettoiera tous les caches, pas seulement le cache du plan. Je préviens normalement, d'utiliser ceci sur un serveur de production en phase de production. Mais comme votre serveur ne fonctionne pas actuellement, vous ne pouvez pas trop leur faire de mal. Cela peut ralentir pendant quelques secondes, peut-être 1-2 minutes, car il doit reconstruire tous les caches, mais après cela, il devrait exécuter les bons plans.

Une autre raison peut être les indices totalement fragmentés. Cela peut être vérifié sur l'ensemble du serveur à l'aide de cette instruction:

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

Si la fragmentation est très élevée, vous devrez peut-être la réorganiser (fragmentation <20%) ou la reconstruire totalement (> 20%). Cela peut augmenter la pression sur votre disque et provoquer des problèmes. D'un autre côté, si les indices sont si mauvais, cela aiderait probablement à la fin plus qu'il ne nuit.

Outre ces deux raisons, il peut encore y avoir un troisième problème

Il se peut que votre serveur soit configuré probablement, vous n'avez changé aucun code dans ce temps, juste ajouté quelques lignes. Toutes les statistiques sont mises à jour et tous les caches sont reconstruits. Tous vos indices sont réorganisés comme vous en avez besoin, mais toujours - rien ne fonctionne. Il se peut que vous ayez atteint la limite de mémoire disponible dans vos processus. Vous en avez peut-être besoin de plus. Vous pouvez simplement vérifier s'il existe un processus qui tente d'obtenir plus de mémoire que vous n'en avez.

Vous pouvez vérifier cela en utilisant cette commande:

SELECT * FROM sys.dm_exec_query_memory_grants

Il vous fournira une liste de toutes les sessions qui consomment de la mémoire. Il peut y avoir une requête qui attend toujours d’obtenir de la mémoire. Ces requêtes peuvent être facilement filtrées. Toutes les sessions où granted_memory_kb IS NULL. Ce sont des sessions qui demandaient de la mémoire mais ne l'obtiennent pas. Une autre chose peut être une mémoire accordée qui peut être trop faible. Vous pouvez comparer les colonnes requested_memory_kbavec granted_memory_kb. Required indique la quantité de mémoire dont le processus a besoin pour fonctionner de manière optimale, tandis que grant affiche la mémoire qui est activée pour le processus. Si un processus a besoin de 2 Go pour s'exécuter mais n'obtient que 2 Mo ... vous pouvez l'obtenir par vous-même. ;-)

Une autre façon consiste à vérifier RESSOURCE_SEMAPHORE:

SELECT * FROM sys.dm_exec_query_resource_semaphore

Vous pouvez jeter un œil aux waiter_countet grantee_count. Si le serveur est au-dessus de 0, vous avez une pression sur votre mémoire, ce qui peut provoquer un échange et provoquer la pression du disque que vous voyez dans le perfmon.

Ionique
la source
0

En plus des pannes de disque possibles, vérifiez l'état de votre sous-système RAID. Nous avons vu quelque chose de similaire et il s'est avéré que la batterie du contrôleur RAID était en panne, il n'y avait donc pas de cache d'écriture disponible - toutes les écritures devaient aller directement sur le disque. Une note latérale - nous pouvions sentir le système s'arrêter pendant que le RDC y pénétrait.

William Jens
la source