Problembehandlung bei hoher CPU-Auslastung in Azure Database for MySQL - Flexibler Server

GILT FÜR: Azure Database for MySQL – Single Server Azure Database for MySQL – Flexible Server

Wichtig

Azure Database for MySQL single server is on the retirement path. Es wird dringend empfohlen, ein Upgrade auf azure Database for MySQL flexiblen Server durchzuführen. Weitere Informationen zum Migrieren zu Azure Database for MySQL flexible Server finden Sie unter Was geschieht mit Azure Database for MySQL Single Server?

Der flexible Azure-Datenbank für MySQL-Server bietet eine Reihe von Metriken, mit denen Sie Ressourcenengpässe und Leistungsprobleme auf dem Server identifizieren können. Um zu bestimmen, ob der Server eine hohe CPU-Auslastung aufweist, überwachen Sie Metriken wie "Host CPU Percent", "Total Connections", "Host Memory Percent" und "IO Percent". Manchmal liefert das Anzeigen einer Kombination dieser Metriken Einblicke in das, was die erhöhte CPU-Auslastung in Ihrer Azure-Datenbank für eine flexible Serverinstanz von MySQL verursachen könnte.

Ziehen Sie beispielsweise einen plötzlichen Anstieg der Verbindungen in Betracht, die einen Anstieg der Datenbankabfragen initiieren, was dazu führt, dass die CPU-Auslastung aufnimmt.

Neben der Erfassung von Metriken ist es wichtig, die Arbeitsauslastung auch zu verfolgen, um zu verstehen, ob eine oder mehrere Abfragen den Anstieg der CPU-Auslastung verursachen.

Hohe CPU-Ursachen

CPU-Spitzen können aus verschiedenen Gründen auftreten, hauptsächlich aufgrund von Spitzen in Verbindungen und schlecht geschriebenen SQL-Abfragen oder einer Kombination aus beiden:

Spitzen in Verbindungen

Wenn sich die Anzahl der Verbindungen erhöht, kommt es auch zu mehr Threads. Dies wiederum kann die CPU-Auslastung steigern, weil diese Verbindungen neben ihren Abfragen und Ressourcen verarbeitet werden müssen. Um probleme mit einer Spitzenanzahl von Verbindungen zu beheben, sollten Sie die Metrik "Gesamt-Verbinden ions" überprüfen und im nächsten Abschnitt weitere Informationen zu diesen Verbindungen finden. Mit performance_schema können Sie ermitteln, welche Hosts und Benutzer gerade mit dem Server verbunden sind. Verwenden Sie dazu die folgenden Befehle:

Gerade verbundene Hosts

   select HOST,CURRENT_CONNECTIONS From performance_schema.hosts
   where CURRENT_CONNECTIONS > 0
   and host not in ('NULL','localhost');

Gerade verbundene Benutzer

   select USER,CURRENT_CONNECTIONS from performance_schema.users
   where CURRENT_CONNECTIONS >0
   and USER not in ('NULL','azure_superuser');

Schlecht geschriebene SQL-Abfragen

Abfragen, deren Ausführung aufwendig ist und bei denen viele Zeilen ohne Index gescannt werden, und Abfragen, bei denen vorübergehende Sortierungen und andere ineffiziente Pläne durchgeführt werden, können eine sehr hohen CPU-Auslastung verursachen. Manche Abfrage lassen sich zwar schnell in einer einzigen Sitzung ausführen, können bei einer Ausführung in mehreren Sitzungen aber CPU-Spitzen auslösen. Daher ist es wichtig, Ihre Abfragen immer zu erläutern, die Sie aus der Anzeigenprozessliste erfassen und sicherstellen, dass ihre Ausführungspläne effizient sind. Dies kann erreicht werden, indem sichergestellt wird, dass sie eine minimale Anzahl von Zeilen mithilfe von Filtern/Wo-Klauseln überprüfen, Indizes verwenden und vermeiden, dass große temporäre Sortierungen zusammen mit anderen fehlerhaften Ausführungsplänen verwendet werden. Weitere Informationen zu Ausführungsplänen finden Sie unter EXPLAIN Output Format.

Erfassen von Details zum aktuellen Workload

Der BEFEHL "SHOW (FULL) PROCESSLIST" zeigt eine Liste aller Benutzersitzungen an, die derzeit mit der flexiblen Serverinstanz von Azure Database für MySQL verbunden sind. Außerdem werden Details zum aktuellen Status und zur Aktivität jeder Sitzung bereitgestellt.

Dieser Befehl erzeugt nur eine Momentaufnahme des aktuellen Sitzungsstatus und stellt keine Informationen zu historischen Sitzungsaktivitäten bereit.

Sehen wir uns die Beispielausgabe der Ausführung dieses Befehls an.

mysql> SHOW FULL PROCESSLIST;
+-------+------------------+--------------------+---------------+-------------+--------+-----------------------------+------------------------------------------+
| Id    | User             | Host               | db            | Command     | Time   | State                       | Info                                     |
+-------+------------------+--------------------+---------------+-------------+--------+-----------------------------+------------------------------------------+
|     1 | event_scheduler  | localhost          | NULL          | Daemon      |     13 | Waiting for next activation | NULL                                     |
|     6 | azure_superuser  | 127.0.0.1:33571    | NULL          | Sleep       |    115 |                             | NULL                                     
|
| 24835 | adminuser        | 10.1.1.4:39296     | classicmodels | Query       |      7 | Sending data                | select * from classicmodels.orderdetails;|
| 24837 | adminuser        | 10.1.1.4:38208     | NULL          | Query       |      0 | starting                    | SHOW FULL PROCESSLIST                    |
+-------+------------------+--------------------+---------------+-------------+--------+-----------------------------+------------------------------------------+
5 rows in set (0.00 sec)

Beachten Sie, dass zwei Sitzungen vorhanden sind, die im Besitz des Benutzers "adminuser" des Kunden sind, beide von derselben IP-Adresse:

  • Sitzung 24835 Hat für die letzten sieben Sekunden eine SELECT-Anweisung ausgeführt.
  • Session 24837 führt die Anweisung "show full processlist" aus.

Bei Bedarf kann es erforderlich sein, eine Abfrage zu beenden, z. B. eine Berichterstellungs- oder HTAP-Abfrage, die dazu geführt hat, dass die CPU-Auslastung ihrer Produktionsauslastung zu einem Anstieg geführt hat. Berücksichtigen Sie jedoch immer die potenziellen Folgen des Beendens einer Abfrage, bevor Sie die Aktion in einem Versuch ausführen, die CPU-Auslastung zu verringern. Andere Zeiten, wenn zeitintensive Abfragen identifiziert werden, die zu CPU-Spitzen führen, optimieren Sie diese Abfragen so, dass die Ressourcen optimal genutzt werden.

Detaillierte aktuelle Workloadanalyse

Sie müssen mindestens zwei Informationsquellen verwenden, um genaue Informationen zum Status einer Sitzung, einer Transaktion und einer Abfrage zu erhalten:

  • Die Prozessliste des Servers aus der „INFORMATION_SCHEMA. PROCESSLIST“-Tabelle, auf die Sie auch zugreifen können, indem Sie den Befehl "SHOW [FULL] PROCESSLIST" ausführen.
  • Transaktionsmetadaten von InnoDB aus der „INFORMATION_SCHEMA. INNODB_TRX“-Tabelle.

Mit Informationen aus nur einer dieser Quellen ist es unmöglich, den Verbindungs- und Transaktionsstatus zu beschreiben. Die Prozessliste informiert Sie beispielsweise nicht darüber, ob eine geöffnete Transaktion mit einer der Sitzungen verknüpft ist. Auf der anderen Seite werden die Transaktionsmetadaten nicht den Sitzungszustand und die in diesem Zustand verbrachten Zeit angezeigt.

Nachfolgend finden Sie eine Beispielabfrage, die Prozesslisteninformationen mit einigen der wichtigen InnoDB-Transaktionsmetadaten kombiniert:

mysql> select    p.id as session_id, p.user, p.host, p.db, p.command, p.time, p.state,    substring(p.info, 1, 50) as info,    t.trx_started, unix_timestamp(now()) - unix_timestamp(t.trx_started) as trx_age_seconds, t.trx_rows_modified, t.trx_isolation_level   from information_schema.processlist p    left join information_schema.innodb_trx t    on p.id = t.trx_mysql_thread_id \G

Das folgende Beispiel zeigt die Ausgabe dieser Abfrage:

*************************** 1. row *************************** 
        session_id: 11 
               user: adminuser 
               host: 172.31.19.159:53624 
                 db: NULL 
            command: Sleep 
               time: 636 
              state: cleaned up 
               info: NULL 
        trx_started: 2019-08-01 15:25:07 
    trx_age_seconds: 2908 
  trx_rows_modified: 17825792 
trx_isolation_level: REPEATABLE READ 
*************************** 2. row *************************** 
         session_id: 12 
               user: adminuser 
               host: 172.31.19.159:53622 
                 db: NULL 
            command: Query 
               time: 15 
              state: executing 
               info: select * from classicmodels.orders 
        trx_started: NULL 
    trx_age_seconds: NULL 
  trx_rows_modified: NULL 
trx_isolation_level: NULL

Eine Analyse dieser Informationen nach Sitzung wird in der folgenden Tabelle aufgeführt.

Bereich Analyse
Sitzung 11 Diese Sitzung ist derzeit im Leerlauf (schlafend), ohne dass Abfragen ausgeführt werden, und dies seit 636 Sekunden. Innerhalb der Sitzung hat eine Transaktion, die für 2 908 Sekunden geöffnet ist, 17 825 792 Zeilen geändert und verwendet die „REPEATABLE READ“-Isolation.
Sitzung 12 Die Sitzung führt derzeit eine SELECT-Anweisung aus, die 15 Sekunden lang ausgeführt wurde. Innerhalb der Sitzung wird keine Abfrage ausgeführt, wie durch die NULL-Werte für „trx_started“ und „trx_age_seconds“ angegeben. Die Sitzung hält weiterhin die Garbage Collection-Grenze ein, solange sie ausgeführt wird, es sei denn, sie verwendet die entspanntere „READ COMMIT“-Isolation.

Beachten Sie, dass, wenn eine Sitzung als Leerlauf gemeldet wird, keine Anweisungen mehr ausgeführt werden. An diesem Punkt hat die Sitzung alle vorherigen Arbeiten abgeschlossen und wartet auf neue Anweisungen vom Client. Leerlaufsitzungen sind jedoch weiterhin für einige CPU-Auslastung und Arbeitsspeichernutzung verantwortlich.

Auflisten geöffneter Transaktionen

Die Ausgabe der folgenden Abfrage enthält eine Liste aller Transaktionen, die derzeit auf dem Datenbankserver ausgeführt werden, um die Startzeit der Transaktion zu ermitteln, sodass Sie leicht erkennen können, ob zeitintensive sowie blockierende Transaktionen vorhanden sind, die die erwartete Laufzeit überschreiten.

SELECT trx_id, trx_mysql_thread_id, trx_state, Unix_timestamp() - ( To_seconds(trx_started) - To_seconds('1970-01-01 00:00:00') ) AS trx_age_seconds, trx_weight, trx_query, trx_tables_in_use, trx_tables_locked, trx_lock_structs, trx_rows_locked, trx_rows_modified, trx_isolation_level, trx_unique_checks, trx_is_read_only FROM information_schema.innodb_trx ORDER BY trx_started ASC;

Grundlegendes zu Threadzuständen

Transaktionen, die zur höheren CPU-Auslastung während der Ausführung beitragen, können Threads in verschiedenen Zuständen aufweisen, wie in den folgenden Abschnitten beschrieben. Verwenden Sie diese Informationen, um den Abfragelebenszyklus und verschiedene Threadzustände besser zu verstehen.

Überprüfen von Berechtigungen/Öffnen von Tabellen

Dieser Zustand bedeutet in der Regel, dass der Vorgang „Tabelle Öffnen“ eine lange Zeit in Anspruch nimmt. Normalerweise können Sie die Tabellencachegröße erhöhen, um das Problem zu verbessern. Tabellen, die langsam geöffnet werden, können jedoch auch auf andere Probleme hinweisen, z. B. dass zu viele Tabellen unter derselben Datenbank vorhanden sind.

Senden von Daten

Während dieser Zustand bedeuten kann, dass der Thread Daten über das Netzwerk sendet, kann er auch angeben, dass die Abfrage Daten vom Datenträger oder Arbeitsspeicher liest. Dieser Zustand kann durch eine sequenzielle Tabellenüberprüfung verursacht werden. Sie sollten die Werte der innodb_buffer_pool_reads und innodb_buffer_pool_read_requests überprüfen, um zu ermitteln, ob eine große Anzahl von Seiten vom Datenträger in den Arbeitsspeicher bereitgestellt wird. Weitere Informationen finden Sie unter Behandeln von Problemen mit geringem Arbeitsspeicher in der Azure-Datenbank für den flexiblen MySQL-Server.

Wird aktualisiert

Dieser Zustand bedeutet in der Regel, dass der Thread einen Schreibvorgang ausführt. Überprüfen Sie die IO-bezogene Metrik im Leistungsmonitor, um ein besseres Verständnis darüber zu erhalten, was die aktuellen Sitzungen tun.

Warten auf <lock_type>-Sperre

Dieser Zustand gibt an, dass der Thread auf eine zweite Sperre wartet. In den meisten Fällen ist es möglicherweise eine Metadatensperre. Sie sollten alle anderen Threads überprüfen und sehen, wer die Sperre übernimmt.

Grundlegendes zu und Analysieren von Warteereignissen

Es ist wichtig, die zugrunde liegenden Wartenereignisse im MySQL-Modul zu verstehen, da lange Wartezeiten oder eine große Anzahl von Wartezeiten in einer Datenbank zu einer erhöhten CPU-Auslastung führen können. Im folgenden Beispiel wird der entsprechende Befehl und die Beispielausgabe angezeigt.

SELECT event_name AS wait_event,
count_star AS all_occurrences,
Concat(Round(sum_timer_wait / 1000000000000, 2), ' s') AS total_wait_time,
 Concat(Round(avg_timer_wait / 1000000000, 2), ' ms') AS
avg_wait_time
FROM performance_schema.events_waits_summary_global_by_event_name
WHERE count_star > 0 AND event_name <> 'idle'
ORDER BY sum_timer_wait DESC LIMIT 10;
+--------------------------------------+-----------------+-----------------+---------------+
| wait_event                           | all_occurrences | total_wait_time | avg_wait_time |
+--------------------------------------+-----------------+-----------------+---------------+
| wait/io/file/sql/binlog              |            7090 | 255.54 s        | 36.04 ms      |
| wait/io/file/innodb/innodb_log_file  |           17798 | 55.43 s         | 3.11 ms       |
| wait/io/file/innodb/innodb_data_file |          260227 | 39.67 s         | 0.15 ms       |
| wait/io/table/sql/handler            |         5548985 | 11.73 s         | 0.00 ms       |
| wait/io/file/sql/FRM                 |            1237 | 7.61 s          | 6.15 ms       |
| wait/io/file/sql/dbopt               |              28 | 1.89 s          | 67.38 ms      |
| wait/io/file/myisam/kfile            |              92 | 0.76 s          | 8.30 ms       |
| wait/io/file/myisam/dfile            |             271 | 0.53 s          | 1.95 ms       |
| wait/io/file/sql/file_parser         |              18 | 0.32 s          | 17.75 ms      |
| wait/io/file/sql/slow_log            |               2 | 0.05 s          | 25.79 ms      |
+--------------------------------------+-----------------+-----------------+---------------+
10 rows in set (0.00 sec)

Einschränken der Ausführungsszeit von SELECT-Anweisungen

Wenn Sie nichts über die Ausführungskosten und die Ausführungszeit für Datenbankvorgänge mit SELECT-Abfragen wissen, können zeitintensive SELECTs zu Unvorhersehbarkeit oder Volatilität auf dem Datenbankserver führen. Die Größe von Anweisungen und Transaktionen sowie die zugeordnete Ressourcenauslastung wächst weiterhin je nach dem zugrunde liegenden Datasetwachstum. Aufgrund dieses ungebundenen Wachstums dauern Endbenutzerauszüge und Transaktionen länger und länger, was immer mehr Ressourcen verbraucht, bis sie den Datenbankserver überwältigen. Wenn Sie ungebundene SELECT-Abfragen verwenden, empfiehlt es sich, den Parameter „max_execution_time“ so zu konfigurieren, dass alle Abfragen, die diese Dauer überschreiten, abgebrochen werden.

Empfehlungen

  • Stellen Sie sicher, dass Ihre Datenbank über genügend Ressourcen verfügt, um Ihre Abfragen auszuführen. Manchmal müssen Sie die Instanzgröße hochskalieren, um mehr CPU-Kerne und zusätzlichen Arbeitsspeicher für Ihren Workload zu erhalten.
  • Vermeiden Sie umfangreiche oder lange Transaktionen, indem Sie sie in kleinere Transaktionen aufteilen.
  • Führen Sie SELECT-Anweisungen nach Möglichkeit auf Lesereplikat-Servern aus.
  • Verwenden Sie Warnungen zur prozentualen Host-CPU-Auslastung, damit Sie benachrichtigt werden, wenn das System einen der angegebenen Schwellenwerte überschreitet.
  • Verwenden Sie Query Performance Insights oder Azure Workbooks, um problematische oder langsam ausgeführte Abfragen zu ermitteln und dann zu optimieren.
  • Erfassen Sie für Datenbankserver in der Produktion in regelmäßigen Abständen Diagnosedaten, um sicherzustellen, dass alles reibungslos ausgeführt wird. Beheben Sie andernfalls die festgestellten Probleme.

Nächste Schritte

Um Antworten anderer Benutzer auf Ihre wichtigsten Fragen zu erhalten oder eine Frage zu veröffentlichen oder zu beantworten, besuchen Sie Stack Overflow.