SQL Server DB wird über Nacht unbrauchbar


9

Gestern war meine SQL Server-Datenbank in Ordnung. Heute ist es fast unbrauchbar - es wird um den Faktor fünf bis zwanzig verlangsamt, je nachdem, wann ich es getroffen habe.

Einige Daten wurden in einem Ladevorgang über Nacht zum Server hinzugefügt, aber nichts wie ein Volume, das eine Datenbank so stark beeinflussen sollte. Etwa 50.000 Nur-Text-Datensätze (kein XML oder andere Frippery).

Der Server wurde heute Morgen gepatcht, bevor wir ihn neu gestartet haben. Keiner unserer anderen Datenbankserver, die ebenfalls gepatcht wurden, verhält sich jedoch anders.

Der Ressourcenmonitor scheint darauf hinzudeuten, dass die Festplatten-E / A fehlerhaft ist. Es läuft die ganze Zeit mit nahezu 100% der Kapazität der MDF-Datei, auch wenn in der Datenbank nicht viel passiert. Der Zugriff auf Templog.ldf ist ebenfalls recht hoch.

Niemand hier ist ein erfahrener DBA (wir sind alle Entwickler mit unterschiedlichen SQL-Kenntnissen) und wir sind alle verblüfft darüber, was passiert ist. Wir haben versucht, sp_updatestats auszuführen und einige der großen Indizes auf verschiedene Discs zu verschieben, ohne Erfolg.

Ich denke, das muss etwas mit dem Patch zu tun haben - es scheint ein zu großer Zufall zu sein. Ein Kollege ist davon überzeugt, dass die Datenlast dazu geführt hat, dass die Größe des MDF so weit gestiegen ist, dass die Ausführungspläne ineffizient wurden.

Was um alles in der Welt hat das verursacht? Wie können wir es herausfinden und was können wir tun, um es zu beheben?

BEARBEITEN:

Die Verwendung sp_WhoIsActiveoffenbart nichts Außergewöhnliches. Es registriert meine eigene Verwendung des Sproc und einiger Befehle eines Kollegen, der gerade versucht, einen anderen Index zu verschieben. Das hält die DB wahrscheinlich gerade auf, aber sie lief vorher genauso schlecht.

Dies ist die Standardversion von SQL Server 2008 R2. SELECT @@VERSIONgibt:

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

Der Server verfügt über 72 GB RAM und drei Quad-Core-2-GHz-Prozessoren.

Das Patching wurde nur auf Windows angewendet. Es gab keine anderen Änderungen als den Patch.

Ausgewählte Einstellungen:

_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

UPDATE: Das Verschieben von Indizes und Tabellen auf verschiedene Festplattenpartitionen scheint die Dinge zu verbessern. Ich bin immer noch verwirrt darüber, wie wir mit so drastischen Ergebnissen so plötzlich einen Wendepunkt hätten erreichen können.


Können Sie sp_whoisactive 5 Minuten lang ausführen und die Ausgabe in der Tabelle erfassen ? Sie können es von hier herunterladen und dies zeigt, wie Sie die Ausgabe in die Tabelle erfassen können
Kin Shah

Wenn Sie den Server neu gestartet haben, bedeutet dies, dass alle zwischengespeicherten Daten aus dem Pufferpool und alle zwischengespeicherten Ausführungspläne gesichert wurden. Dies bedeutet, dass SQL Server beide hochfahren muss - jeder Ausführungsplan muss neu kompiliert werden, und wenn die Statistiken veraltet sind, erhalten Sie möglicherweise nicht die effizientesten Pläne. Dies bedeutet auch, dass Daten von der Festplatte in den Speicher eingelesen werden müssen, während sie vor dem Neustart wahrscheinlich zusammen mit den Daten im Speicher summten. Dies sollte von kurzer Dauer sein.
Aaron Bertrand

@ AaronBertrand Es ist seit acht Stunden so. Wir starten den Server regelmäßig zum Patchen neu und haben so etwas noch nie bemerkt.
Bob Tway

1
Verwenden Sie die Benutzeroberfläche nicht, um nach Konfigurationseinstellungen zu suchen. SELECT * FROM sys.configurations;- Sie wollen value, value_in_usefür Dinge wie max server memory (MB). Auch die Build-Nummer in SELECT @@VERSION;wäre nützlich, sowie ob sich diese in einem Hypervisor befindet und ob sich auf dem Host seit gestern (oder seit dem letzten Neustart von SQL Server) etwas geändert hat.
Aaron Bertrand

2
Welche Art von E / A-Subsystem verwenden Sie? SAN, lokale Festplatte usw.? Gibt es eine Chance, dass Sie zufällig eine schlechte Fahrt haben? Sind Ihre DBs auch am selben Speicherort wie Betriebssystemdateien gespeichert? Und letzte Frage. Ein Teil unseres Prozesses vor einem Betriebssystem-Upgrade bestand darin, zuvor einen VM-Snapshot zu erstellen. Leider hat der Verantwortliche vergessen, es zu begehen. Sehr schnell wurde das ganze System langsamer und langsamer. Gibt es eine Chance, dass dir das passiert ist?
Kenneth Fisher

Antworten:


3

Es kann vorkommen, dass eine kleine Datenmenge im SQL Server eine bestimmte Grenze erreicht, um einen anderen Plan oder ähnliches zu erzwingen. Dies ist nicht unwahrscheinlich. Aber die Tatsache, dass Ihre CD stark im Dienst zu sein scheint, bringt mich zu einer anderen Schlussfolgerung.

Es gibt zwei mögliche Grundgründe für Ihre Verlangsamung.

  1. Sie haben Ihr System aktualisiert und neu gestartet
  2. Sie laden eine Reihe von Daten hinein

Werfen wir einen Blick auf Teil Nr. 1

Möglicherweise ist Ihre SQL Server-Konfiguration fehlerhaft. Dies kann schwerwiegende Probleme hinsichtlich der Servergeschwindigkeit und der Disc-Nutzung verursachen.

Bitte überprüfen Sie zunächst Ihre grundlegenden Servereinstellungen. Diese Grundeinstellungen sind max server memory, affinity I/O mask, affinity maskund max degree of parallelism. Möglicherweise müssen Sie die erweiterten Optionen mit aktivieren show advanced options.

Hier ist ein vollständiges Skript:

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

Vergleichen Sie das Ergebnis mit Ihren dokumentierten Werten in Ihren Installationsschritten. Sind sie immer noch gleich?

Es kann viele Gründe haben, warum sich Ihr Server so seltsam verhält. Normalerweise würde ich wetten, dass du max server memoryeinfach falsch liegst. Dies führt dazu, dass Ihr SQL Server Datenseiten dauerhaft austauscht. Er kann nicht alles in Erinnerung behalten. Dies bedeutet, dass er die Seiten von der CD lesen, aktualisieren und sofort zurückschreiben muss. Wenn ein anderes Update kommt und dieselbe Seite für ein Update verwendet, kann es nicht aus dem Speicher gelesen werden. Stattdessen muss der Server es erneut von der Disc lesen. Einfach tauschen ...

Ein weiteres Problem kann eine zu hohe Affinität zu Discs oder Prozessen sein. Wenn Sie einen gemeinsam genutzten Server (SQL Server + andere Dienste) mit einer dedizierten CD für SQL Server verwendet haben (was zwar selten vorkommt, aber der Fall sein kann), könnte dies Ihr Problem sein. Ihr Server hatte normalerweise beispielsweise 3 CPU für Prozesse und einen für E / A. Die anderen 12 CPU werden für andere Dienste verwendet. In diesem Fall ist Ihre Affinitätsmaske falsch und verwendet beispielsweise eine automatische Konfiguration. Dies bedeutet, dass Ihr Server alle 16 Kerne für Prozesse und E / A dynamisch verwendet. Wenn große Prozesse ausgeführt werden, kann dies zu einer enormen Belastung der Disc führen, die möglicherweise nicht verarbeitet wird. Tatsächlich glaube ich aber nicht, dass dies Ihr Fall ist. Es wäre schneller (wenn auch nur ein bisschen), wenn dies zutreffen würde, aber Ihr Fall ist eine Verlangsamung.

Ein weiteres Problem kann ein zu hoher Grad an Parallelität sein. Dies bedeutet, dass in einem Teil einer Abfrage zu viele Threads im Leerlauf sind. Dies kann auch zu einer enormen Verlangsamung führen, wenn die Parallelität nicht wie erwartet funktioniert. Dies beschreibt jedoch nicht Ihre hohe E / A insgesamt.

Schauen wir uns jetzt auch Teil Nr. 2 an

Sie laden eine Reihe von Zeilen in Ihr System. Selbst wenn dies ein regulärer Job ist, kann dies zu einer Begrenzung führen, in der Ihre Abfragepläne eskalieren. Es kann sogar vorkommen, dass Ihre Einfügung in Kombination mit SQL Server dieses Verhalten erzeugt.

Sie haben erwähnt, dass Sie bereits versucht haben, Ihre Indizes auf eine andere CD zu migrieren, was zu helfen scheint. Dies kann nur daran liegen, dass Sie die Last auf zwei verschiedene Discs aufgeteilt haben.

Es kann sein, dass Ihre Indizes gebrochen wurden, dass Ihre Pläne gebrochen wurden oder dass Ihre Statistiken einfach veraltet sind.

1. Lassen Sie uns die letzte Aktualisierung der Statistik überprüfen. Sie können dies manuell über die Schnittstelle für jedes einzelne Statistikelement tun. Welches wäre ein Schmerz. Oder Sie können diesen Code ausprobieren:

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

Auf diese Weise erhalten Sie vollständige Informationen zu jedem Index (und Heap) und den dahinter stehenden Statistiken. Selbst wenn Sie ausführen sp_updatestats, bedeutet dies nicht, dass die Statistiken aktualisiert wurden. Der Teil, wenn ein Update ziemlich schwierig ist, selbst wenn Sie es ausführen sp_updatestatsoder wenn auto update statisticses aktiviert ist, werden die Statistiken nicht rechtzeitig aktualisiert. Hier sind einige Randpunkte, wenn ein Update benötigt / generiert wird:

  • Eine leere Tabelle erhält eine oder mehrere Zeilen
  • Eine Tabelle mit mehr als 500 Zeilen aktualisiert 20% + 500 zusätzliche Zeilen, und anschließend erfolgt eine Einfügung
  • Wenn 500 Zeilen in einer Tabelle geändert wurden, die weniger als 500 Zeilen enthält

Dies bedeutet, dass Ihre Statistiken möglicherweise veraltet sind, selbst wenn Sie das Update ausführen.

Sie können sich die Abfrage oben ansehen. Wenn Sie in einigen Tabellen ziemlich alte Statistiken finden, möchten Sie möglicherweise eine manuelle Statistikaktualisierung für diese Tabelle ausführen:

UPDATE STATISTICS dbo.YourBadTable WITH FULLSCAN

Danach möchten Sie Ihrem Server vielleicht einen Tritt in den Arsch geben, um alle alten Pläne wegzuwerfen.

DBCC FREEPROCCACHE 

Wenn Sie nur alle Caches bereinigen möchten, möchten Sie möglicherweise Folgendes ausführen:

DBCC FREESYSTEMCACHE ('ALL')

Dadurch werden alle Caches bereinigt, nicht nur der Plan-Cache. Normalerweise würde ich warnen, dies auf einem Produktionsserver in der Produktionsphase zu verwenden. Da Ihr Server derzeit nicht funktioniert, können Sie ihm nicht zu viel Schaden zufügen. Es kann sich für einige Sekunden verlangsamen, vielleicht 1-2 Minuten, da er alle Caches neu erstellen muss, aber danach sollte er mit den richtigen Plänen laufen.

Ein weiterer Grund können vollständig fragmentierte Indizes sein. Dies kann auf dem gesamten Server mit folgender Anweisung überprüft werden:

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

Wenn die Fragmentierung sehr hoch ist, müssen Sie sie möglicherweise neu organisieren (Fragmentierung <20%) oder vollständig neu erstellen (> 20%). Dies kann mehr Druck auf Ihre Disc ausüben und Probleme verursachen. Auf der anderen Seite, wenn die Indizes so schlecht sind, würde es am Ende wahrscheinlich mehr helfen, als es schadet.

Neben diesen beiden Gründen kann es noch ein drittes Problem geben

Möglicherweise ist Ihr Server konfiguriert, Sie haben in dieser Zeit keinen Code geändert, sondern nur ein paar Zeilen hinzugefügt. Alle Statistiken werden aktualisiert und alle Caches werden neu erstellt. Alle Ihre Indizes werden so neu organisiert, wie Sie sie benötigen, aber dennoch - nichts funktioniert. Möglicherweise haben Sie in Ihren Prozessen die Grenze des verfügbaren Speichers erreicht. Vielleicht brauchst du mehr. Sie können einfach überprüfen, ob es einen Prozess gibt, der versucht, mehr Speicher als Sie zu erhalten.

Sie können dies mit diesem Befehl überprüfen:

SELECT * FROM sys.dm_exec_query_memory_grants

Sie erhalten eine Liste aller Sitzungen, die Speicher verbrauchen. Möglicherweise wartet eine Abfrage noch auf den Speicher. Diese Abfragen können leicht gefiltert werden. Alle Sitzungen wo granted_memory_kb IS NULL. Dies sind Sitzungen, die Speicher angefordert haben, diesen aber nicht erhalten. Eine andere Sache kann ein gewährter Speicher sein, der zu niedrig sein kann. Sie können die Spalten requested_memory_kbmit vergleichen granted_memory_kb. Angefordert zeigt an, wie viel Speicher der Prozess benötigt, um optimal ausgeführt zu werden, während er gewährt wird. Der für den Prozess aktivierte Speicher wird angezeigt. Wenn ein Prozess 2 GB benötigt, um ausgeführt zu werden, aber nur 2 MB erhält, erhalten Sie ihn möglicherweise selbst. ;-);

Eine andere Möglichkeit besteht darin, Folgendes zu überprüfen RESSOURCE_SEMAPHORE:

SELECT * FROM sys.dm_exec_query_resource_semaphore

Sie können sich das waiter_countund das ansehen grantee_count. Wenn der Kellner über 0 liegt, haben Sie Druck auf Ihr Gedächtnis, was zu einem Austausch und dem von Ihnen im Perfmon beobachteten Scheibendruck führen kann.


0

Überprüfen Sie zusätzlich zu möglichen Laufwerksfehlern den Status Ihres RAID-Subsystems. Wir haben etwas Ähnliches gesehen und es stellte sich heraus, dass der Akku des RAID-Controllers ausgefallen ist, sodass kein Schreibcache verfügbar war - alle Schreibvorgänge mussten direkt auf die Festplatte gehen. Eine Randnotiz - wir konnten fühlen, wie das System pausierte, während RDC in das System einstieg.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.