Ich habe ein 4-Knoten-AG-Setup wie folgt:
VM-Hardwarekonfiguration aller Knoten:
- Microsoft SQL Server 2017 Enterprise Edition (RTM-CU14) (KB4484710)
- 16 vCPUs
- 356 GB RAM (lange Geschichte zu diesem ...)
- Maximaler Parallelitätsgrad: 1 (wie vom App-Anbieter gefordert)
- Kostenschwelle für Parallelität: 50
- Maximaler Serverspeicher (MB): 338944 (331 GB)
AG Konfiguration:
- Knoten 1: Primäre oder synchrone Festschreibung Nicht lesbar Sekundär, konfiguriert für automatisches Failover
- Knoten 2: Primäre oder synchrone Festschreibung Nicht lesbar Sekundär, konfiguriert für automatisches Failover
- Knoten 3: Lesbarer Sekundärsatz mit asynchronem Commit, konfiguriert für manuelles Failover
- Knoten 4: Lesbarer Sekundärsatz mit asynchronem Commit, konfiguriert für manuelles Failover
Die fragliche Frage:
Diese Abfrage ist nicht besonders verrückt. Sie enthält eine Zusammenfassung der ausstehenden Arbeitselemente in verschiedenen Warteschlangen innerhalb der Anwendung. Sie können den Code über einen der folgenden Ausführungsplan-Links sehen.
Ausführungsverhalten auf dem Primärknoten:
Bei der Ausführung auf dem Primärknoten liegt die Ausführungszeit im Allgemeinen um die 1-Sekunden-Marke. Hier ist der Ausführungsplan. Nachfolgend sind die Statistiken aufgeführt, die von STATISTICS IO und STATISTICS TIME vom Primärknoten erfasst wurden:
(347 rows affected)
Table 'Worktable'. Scan count 647, logical reads 2491, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'workitemlc'. Scan count 300, logical reads 7125, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'Workfile'. Scan count 0, logical reads 0, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'schedulertask'. Scan count 1, logical reads 29, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'wfschedulertask'. Scan count 1, logical reads 9, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'schedulerservice'. Scan count 1, logical reads 12, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'schedulerworkerpool'. Scan count 1, logical reads 3, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'itemlc'. Scan count 1, logical reads 26372, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
(1 row affected)
SQL Server Execution Times:
CPU time = 500 ms, elapsed time = 656 ms.
SQL Server parse and compile time:
CPU time = 0 ms, elapsed time = 0 ms.
Ausführungsverhalten auf dem schreibgeschützten Sekundärknoten:
Bei der Ausführung auf einem schreibgeschützten sekundären Knoten (dh Knoten 3 oder Knoten 4) verwendet diese Abfrage denselben Ausführungsplan (dies ist eine andere Planverknüpfung), und es werden ungefähr dieselben Ausführungsstatistiken angezeigt (z. B. kann es einige weitere Seiten geben Scans, da sich diese Ergebnisse ständig ändern), aber mit Ausnahme der CPU-Zeit sehen sie sehr ähnlich aus. Hier sind Statistiken, die aus STATISTICS IO und STATISTICS TIME vom schreibgeschützten Sekundärknoten erfasst wurden:
(347 rows affected)
Table 'Worktable'. Scan count 647, logical reads 2491, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'workitemlc'. Scan count 300, logical reads 7125, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'Workfile'. Scan count 0, logical reads 0, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'schedulertask'. Scan count 1, logical reads 29, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'wfschedulertask'. Scan count 1, logical reads 9, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'schedulerservice'. Scan count 1, logical reads 12, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'schedulerworkerpool'. Scan count 1, logical reads 3, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'itemlc'. Scan count 1, logical reads 26372, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
(1 row affected)
SQL Server Execution Times:
CPU time = 55719 ms, elapsed time = 56335 ms.
SQL Server parse and compile time:
CPU time = 0 ms, elapsed time = 0 ms.
Andere Details:
Ich habe auch beide sp_WhoIsActive
und Paul RandalsWaitingTasks.sql
Skript auf der Sekundärseite ausgeführt, während diese Abfrage ausgeführt wird, aber ich sehe keine Wartezeiten, was ehrlich gesagt frustrierend ist:
Dies scheint auch kein Fall von AG-Latenz zu sein, da der Synchronisationsstatus tatsächlich recht gut ist:
--https://sqlperformance.com/2015/08/monitoring/availability-group-replica-sync
SELECT
ar.replica_server_name,
adc.database_name,
ag.name AS ag_name,
drs.is_local,
drs.synchronization_state_desc,
drs.synchronization_health_desc,
--drs.last_hardened_lsn,
--drs.last_hardened_time,
drs.last_redone_time,
drs.redo_queue_size,
drs.redo_rate,
(drs.redo_queue_size / drs.redo_rate) / 60.0 AS est_redo_completion_time_min,
drs.last_commit_lsn,
drs.last_commit_time
FROM sys.dm_hadr_database_replica_states AS drs
INNER JOIN sys.availability_databases_cluster AS adc
ON drs.group_id = adc.group_id AND
drs.group_database_id = adc.group_database_id
INNER JOIN sys.availability_groups AS ag
ON ag.group_id = drs.group_id
INNER JOIN sys.availability_replicas AS ar
ON drs.group_id = ar.group_id AND
drs.replica_id = ar.replica_id
ORDER BY
ag.name,
ar.replica_server_name,
adc.database_name;
Diese Abfrage scheint der schlimmste Täter zu sein. Andere Abfragen, die auf dem Primärknoten ebenfalls weniger als eine Sekunde dauern, können auf dem Sekundärknoten 1 bis 5 Sekunden dauern, und obwohl das Verhalten nicht so schwerwiegend ist, scheint es Probleme zu verursachen.
Schließlich habe ich mir auch die Server angesehen und nach externen Prozessen wie A / V-Scans, externen Jobs, die unerwartete E / A erzeugen, usw. gesucht und bin mit leeren Händen aufgetaucht. Ich glaube nicht, dass dies durch irgendetwas außerhalb des SQL Server-Prozesses verursacht wird.
Die Frage:
Es ist erst Mittag, wo ich bin, und es war schon ein langer Tag, also vermute ich, dass mir hier etwas Offensichtliches fehlt. Entweder das, oder wir haben etwas falsch konfiguriert, was möglich ist, da wir eine Reihe von Anrufen beim Anbieter und in der MS im Zusammenhang mit dieser Umgebung erhalten haben.
Bei all meinen Nachforschungen kann ich einfach nicht herausfinden, was diesen Leistungsunterschied verursacht. Ich würde erwarten, dass auf den sekundären Knoten eine Art Wartezeit auftritt, aber nichts. Wie kann ich dieses Problem weiter beheben, um die Grundursache zu ermitteln? Hat jemand dieses Verhalten schon einmal gesehen und einen Weg gefunden, es zu beheben?
UPDATE Nr. 1
Nachdem die Status des dritten Knotens (eines der schreibgeschützten Replikate) in nicht lesbare und dann als Test wieder in lesbar getauscht wurden, wird dieses Replikat weiterhin von einer offenen Transaktion aufgehalten, wobei alle Clientabfragen das anzeigen HADR_DATABASE_WAIT_FOR_TRANSITION_TO_VERSIONING
warten.
Das Ausführen eines DBCC OPENTRAN
Befehls führt zu folgenden Ergebnissen:
Oldest active transaction:
SPID (server process ID): 420s
UID (user ID) : -1
Name : QDS nested transaction
LSN : (941189:33148:8)
Start time : May 7 2019 12:54:06:753PM
SID : 0x0
DBCC execution completed. If DBCC printed error messages, contact your system administrator.
Wenn Sie diese SPID nachschlagen sp_who2
, wird sie als BACKGROUND
Prozess angezeigt , der QUERY STORE BACK
als Befehl aufgeführt ist.
Obwohl wir in der Lage sind, TLog-Backups zu erstellen, vermute ich, dass wir auf ähnliche Funktionen dieses behobenen Fehlers stoßen. Daher plane ich, heute ein Ticket mit MS zu diesem speziellen Problem zu eröffnen.
Abhängig vom Ergebnis dieses Tickets werde ich versuchen, einen Call-Stack-Trace gemäß Joes Vorschlag zu erfassen und zu sehen, wohin wir gehen.
Endgültiges Update (Problem selbst behoben)
Nachdem die 52-Stunden-Marke der offenen Query Store-Transaktion (wie oben angegeben) überschritten wurde, entschied sich die AG für ein automatisches Failover. Bevor dies geschah, habe ich einige zusätzliche Metriken abgerufen. Über diesen von Sean bereitgestellten Link verfügte die betreffende Datenbank über einen sehr großen Versionsspeicher, der dieser Datenbank gewidmet war, insbesondere an einem Punkt, an dem ich 1651360 Seiten im reserved_page_count
Feld und 13210880 für den reserved_space_kb
Wert aufgezeichnet hatte .
Gemäß den ERRORLOGs trat das Failover nach einer 5-minütigen Flut von Transaktionshärtungsfehlern im Zusammenhang mit QDS base transaction
und QDS nested transaction
Transaktionen auf.
Das Failover verursachte in meinem Fall einen Ausfall von etwa 10 Minuten. Die Datenbank hat eine Größe von ~ 6 TB und ist sehr aktiv, was meiner Meinung nach eigentlich ziemlich gut war. Während der neuen Primärknoten während dieser Zeit online war, konnten keine Clientabfragen abgeschlossen werden, da alle auf den QDS_LOADDB
Wartetyp warteten .
Nach dem Failover wurden die Versionsspeichernummern auf 176 für reserved_page_count
und 1408 für reduziert reserved_space_kb
. Abfragen für die sekundären schreibgeschützten Replikate wurden ebenfalls so schnell ausgeführt, als ob sie vom primären ausgeführt würden. Es sieht also so aus, als wäre das Verhalten infolge des Failovers vollständig verschwunden.
QDS_LOADDB
- wenn Sie dies in Zukunft vermeiden möchten, aber den Query Store weiterhin aktiviert lassen möchten, können Sie diese von Microsoft empfohlenen Trace-Flags verwenden . Insbesondere lässt 7752 Abfragen ausführen, bevor der Abfragespeicher initialisiert wurde (sodass Sie möglicherweise einige Abfragen verpassen, Ihre Datenbank jedoch aktiv ist).
7752
sieht besonders nützlich aus. Danke für den Tipp!