Cloud SQL for MySQL von Google Cloud ist ein vollständig verwalteter Datenbankdienst, mit dem Sie Ihre MySQL-, PostgreSQL- oder SQL Server-Datenbank auf der Google Cloud Platform einrichten, pflegen und verwalten können. Cloud SQL führt eine große Anzahl von MySQL-Datenbanken in seinem Bestand aus. Es ist nicht ungewöhnlich, dass einige MySQL-Instanzen viel Arbeitsspeicher verbrauchen und aufgrund eines Fehlers wegen unzureichenden Arbeitsspeichers (OOM) abstürzen. In diesem Artikel erfahren Sie, wie Sie Probleme mit dem MySQL-Speicher beheben können.
Eine Situation mit unzureichendem Arbeitsspeicher tritt auf, wenn ein Prozess versucht, Arbeitsspeicher zuzuweisen, und schlägt fehl, weil auf dem Server kein Arbeitsspeicher verfügbar ist. Dies führt häufig zum Linux OOM Killer, einem Prozess, der vom Linux-Kernel verwendet wird, wenn das System sehr wenig Arbeitsspeicher hat, und den Datenbankprozess beendet.
Ein Datenbankabsturz aufgrund einer OOM-Bedingung ist nicht ideal, da der Datenbankprozess mit der SIGKILL-Anweisung beendet wird, wodurch die Anwendung keine Chance auf ein normales Herunterfahren von MySQL hat. Dies verursacht die folgenden Probleme:
MySQL fügt in performance_schema eine Speicherinstrumentierung hinzu, die das Verständnis der MySQL-Arbeitsspeicherzuweisung erleichtert. In diesem Artikel erfahren Sie, wie Sie MySQL-Arbeitsspeicherprobleme mithilfe von „performance_schema“ beheben.
Jede Cloud SQL-Instanz wird von einer virtuellen Maschine (VM) betrieben, die auf einem Google Cloud-Hostserver ausgeführt wird. Jede VM betreibt das Datenbankprogramm, z. B. MySQL Server und Dienst-Agents, die unterstützende Dienste wie Logging und Monitoring bereitstellen. Cloud SQL reserviert einen Teil des Arbeitsspeichers für das Betriebssystem und die Dienst-Agents und weist den verbleibenden Arbeitsspeicher für Datenbankprogramme wie mysqld zu.
Die folgende Tabelle zeigt die Arbeitsspeicherzuweisung für den mysqld-Prozess und die Standardkonfiguration des InnoDB-Zwischenspeicherpools für jeden Maschinentyp.
Maschinentyp | Instanz-RAM GIB (Byte) | mysqld-Arbeitsspeicher (GB) | InnoDB-Pufferpool – GiB (Byte) | Pufferpool (% des Instanz-RAM) | Pufferpool (% des MySQLd-Arbeitsspeichers) |
db-g1-small | 1.7(1825361101) | 1.11 | 0.625(671088640) | 37 % | 56 % |
db-custom-1-3840 | 3.75(4026531840) | 2,97 | 1.375(1476395008) | 37 % | 46 % |
db-custom-2-7680 | 7.5(8053063680) | 6.72 | 4(4294967296) | 53 % | 60 % |
db-custom-2-13312 | 13(13958643712) | 12 | 9(9663676416) | 69 % | 75 % |
db-custom-4-15360 | 15(16106127360) | 14 | 10.5(11274289152) | 70 % | 76 % |
db-custom-4-26624 | 26(27917287424) | 24 | 19(20401094656) | 73 % | 79 % |
db-custom-8-30720 | 30(32212254720) | 28 | 22(23622320128) | 73 % | 80 % |
db-custom-8-53248 | 52(55834574848) | 48 | 38(40802189312) | 73 % | 79 % |
db-custom-16-61440 | 60(64424509440) | 55 | 44(47244640256) | 73 % | 80 % |
db-custom-16-106496 | 104(111669149696) | 96 | 75(80530636800) | 72 % | 78 % |
db-custom-32-122880 | 120(128849018880) | 110 | 87(93415538688) | 73 % | 79 % |
db-custom-32-212992 | 208(223338299392) | 191 | 150(161061273600) | 72 % | 78 % |
db-custom-64-245760 | 240(257698037760) | 221 | 173(185757335552) | 72 % | 78 % |
db-custom-96-368640 | 360(386547056640) | 331 | 260(279172874240) | 72 % | 79 % |
db-custom-64-425984 | 416(446676598784) | 383 | 300(322122547200) | 72 % | 78 % |
db-custom-96-638976 | 624(670014898176) | 574 | 450(483183820800) | 72 % | 78 % |
Maschinentyp
Instanz-RAM GIB (Byte)
mysqld-Arbeitsspeicher (GB)
InnoDB-Pufferpool – GiB (Byte)
Pufferpool (% des Instanz-RAM)
Pufferpool (% des MySQLd-Arbeitsspeichers)
db-g1-small
1.7(1825361101)
1.11
0.625(671088640)
37 %
56 %
db-custom-1-3840
3.75(4026531840)
2,97
1.375(1476395008)
37 %
46 %
db-custom-2-7680
7.5(8053063680)
6.72
4(4294967296)
53 %
60 %
db-custom-2-13312
13(13958643712)
12
9(9663676416)
69 %
75 %
db-custom-4-15360
15(16106127360)
14
10.5(11274289152)
70 %
76 %
db-custom-4-26624
26(27917287424)
24
19(20401094656)
73 %
79 %
db-custom-8-30720
30(32212254720)
28
22(23622320128)
73 %
80 %
db-custom-8-53248
52(55834574848)
48
38(40802189312)
73 %
79 %
db-custom-16-61440
60(64424509440)
55
44(47244640256)
73 %
80 %
db-custom-16-106496
104(111669149696)
96
75(80530636800)
72 %
78 %
db-custom-32-122880
120(128849018880)
110
87(93415538688)
73 %
79 %
db-custom-32-212992
208(223338299392)
191
150(161061273600)
72 %
78 %
db-custom-64-245760
240(257698037760)
221
173(185757335552)
72 %
78 %
db-custom-96-368640
360(386547056640)
331
260(279172874240)
72 %
79 %
db-custom-64-425984
416(446676598784)
383
300(322122547200)
72 %
78 %
db-custom-96-638976
624(670014898176)
574
450(483183820800)
72 %
78 %
Bei Instanzen mit 10 GB RAM und mehr ist der mysqld-Prozess auf 92% des Instanz-RAM beschränkt. Der InnoDB-Pufferpool ist auf 75 bis 80% des für den mysqld-Prozess verfügbaren Arbeitsspeichers konfiguriert. Neben dem InnoDB-Pufferpool weist MySQL mehrere Puffer und Caches zu, um die Leistung zu verbessern. Weitere Informationen zur Arbeitsspeicherzuweisung in MySQL finden Sie in diesem Artikel.
Wenn die Arbeitsspeichernutzung von mysqld das konfigurierte Limit des mysqld-Prozesses überschreitet, beendet der Linux-OOM-Killer den mysqld-Prozess, da er der größte Arbeitsspeichernutzer der Instanz ist.
performance_schema ist ein MySQL-Feature zur Überwachung der Serverausführung auf niedriger Ebene. Mit Cloud SQL for MySQL kann „performance_schema“ auf Instanzen mit einer RAM-Größe von mindestens 3 GB aktiviert werden. Ab MySQL 8.0 ist es in Instanzen mit mindestens 15 GB RAM standardmäßig aktiviert.
Performance_schema ist für MySQL 5.6 und 5.7 standardmäßig deaktiviert. Es kann mithilfe von Datenbank-Flags aktiviert werden.
Das Aktivieren von „performance_schema“ ist mit einem gewissen Leistungsaufwand sowie Auswirkungen auf den Arbeitsspeicher verbunden. Informationen zur Arbeitsspeicherzuweisung finden Sie im Artikel zum Arbeitsspeicher-Zuordnungsmodell des Leistungsschemas.
Performance_schema hilft bei der Überwachung der Speichernutzung in MySQL. Speicherinstrumente haben Namen in Form von memory/code_area/instrument_name, wobei code_area ein Wert wie sql oder Innodb ist und instrument_name das Instrumentendetail ist.
MySQL 5.7 aktiviert einige Speicherinstrumente standardmäßig, aber nicht alle. Sie können sie aktivieren, indem Sie in der Tabelle performance_schema.setup_instruments die Spalte AKTIVIERT aktualisieren.
mysql> select version();
+-------------------+
| version() |
+-------------------+
| 5.7.39-google-log |
+-------------------+
1 row in set (0.00 sec)
mysql> SELECT enabled, count(*) FROM performance_schema.setup_instruments WHERE NAME LIKE '%memory%' group by enabled;
+---------+----------+
| enabled | count(*) |
+---------+----------+
| YES | 70 |
| NO | 306 |
+---------+----------+
2 rows in set (0.00 sec)
mysql> UPDATE performance_schema.setup_instruments SET ENABLED = 'YES' WHERE NAME LIKE 'memory/%';
Query OK, 306 rows affected (0.00 sec)
Rows matched: 376 Changed: 306 Warnings: 0
mysql> SELECT enabled, count(*) FROM performance_schema.setup_instruments WHERE NAME LIKE '%memory%' group by enabled;
+---------+----------+
| enabled | count(*) |
+---------+----------+
| YES | 376 |
+---------+----------+
1 row in set (0.00 sec)
Wenn Sie zur Laufzeit Speicherinstrumente aktivieren, werden nur die Speicherobjekte gezählt, die nach der Aktivierung der Instrumentierung erstellt wurden. Zur Fehlerbehebung wird daher empfohlen, zu warten, bis der Server genügend Daten gesammelt hat.
MySQL 8.0 aktiviert standardmäßig alle Speicherinstrumente.
mysql> select version();
+---------------+
| version() |
+---------------+
| 8.0.28-google |
+---------------+
1 row in set (0.00 sec)
mysql> SELECT enabled, count(*) FROM performance_schema.setup_instruments WHERE NAME LIKE '%memory%' group by enabled;
+---------+----------+
| enabled | count(*) |
+---------+----------+
| YES | 490 |
+---------+----------+
1 row in set (0.00 sec)
Das Sys-Schema enthält viele Ansichten, in denen „performance_schema“-Daten in leicht verständlichen Formen zusammengefasst werden. Die meisten dieser Aufrufe sind paarweise möglich. Sie haben den gleichen Namen und einer von ihnen hat das Präfix x$. Die folgenden Ansichten sind in MySQL 5.7 und 8.0 verfügbar, um die Arbeitsspeicherzuweisung auf verschiedenen Ebenen anzusehen.
MySQL use sys;
Datenbank geändert
mysql> zeigt Tabellen wie '%memory%' an;
+-------------------------------------+
| Tables_in_sys (%memory%) |
+-------------------------------------+
| memory_by_host_by_current_bytes |
| memory_by_thread_by_current_bytes |
| memory_by_user_by_current_bytes |
| memory_global_by_current_bytes |
| memory_global_total |
| x$memory_by_host_by_current_bytes |
| x$memory_by_thread_by_current_bytes |
| x$memory_by_user_by_current_bytes |
| x$memory_global_by_current_bytes |
| x$memory_global_total |
+-------------------------------------+
10 rows in set (0.02 sec)
Die Ansicht sys.memory_global_total fasst die gesamte Arbeitsspeichernutzung in einem lesbaren Format zusammen.
mysql> select * from sys.memory_global_total;
+-----------------+
| total_allocated |
+-----------------+
| 12.43 GiB |
+-----------------+
1 row in set (0.44 sec)
sys.x$memory_global_total zeigt die gleichen Informationen an, jedoch in Byte.
mysql> select * from sys.x$memory_global_total;
+-----------------+
| total_allocated |
+-----------------+
| 13351482992 |
+-----------------+
1 row in set (1.39 sec)
Die Ansicht ohne das Präfix x$ soll benutzerfreundlicher und leichter lesbar sein. Die Ansicht mit dem Präfix x$, die dieselben Werte im Rohformat anzeigt, ist eher für die Verwendung mit anderen Tools vorgesehen, die die Daten selbst verarbeiten.
Die Ansicht „sys.memory_global_by_current_bytes“ zeigt die aktuelle Arbeitsspeichernutzung, gruppiert nach dem Zuweisungstyp (event_name), z. B. „memory/innodb/buf_buf_pool“ (InnoDB-Zwischenspeicherpool). Standardmäßig werden Zeilen absteigend nach dem verwendeten Arbeitsspeicher sortiert.
Bevor wir uns die einzelnen Zuweisungstypen genauer ansehen, ist es empfehlenswert, einen Überblick über die Arbeitsspeichernutzung für jeden Codebereich wie Innodb, SQL, performance_schema usw. zu haben.
Die folgende Abfrage aggregiert den aktuell zugewiesenen Speicher nach dem Codebereich.
SELECT SUBSTRING_INDEX(event_name,'/',2) AS code_area,
FORMAT_BYTES(SUM(current_alloc)) AS current_alloc
FROM sys.x$memory_global_by_current_bytes
GROUP BY SUBSTRING_INDEX(event_name,'/',2)
ORDER BY SUM(current_alloc) DESC;
+---------------------------+---------------+
| code_area | current_alloc |
+---------------------------+---------------+
| memory/innodb | 11.28 GiB |
| memory/performance_schema | 520.02 MiB |
| memory/temptable | 514.00 MiB |
| memory/sql | 106.12 MiB |
| memory/mysys | 43.25 MiB |
| memory/vio | 372.15 KiB |
| memory/myisam | 696 Byte |
| memory/csv | 88 Byte |
| memory/blackhole | 88 Byte |
+---------------------------+---------------+
9 rows in set (1.02 sec)
Diese Ausgabe zeigt, dass innodb der größte Arbeitsspeicherverbraucher ist, gefolgt von performance_schema und temporären Tabellen.
Wenn Sie jetzt „sys.memory_global_by_current_bytes“ abfragen, wird die Arbeitsspeichernutzung für interne MySQL-Strukturen angezeigt, wie in der Spalte „event_name“ beschrieben. Wenn Sie die ungewöhnliche Speichererweiterung beheben möchten, können Sie die Ursache anhand der Ausgabe dieser Ansicht identifizieren.
mysql> select event_name,current_alloc,high_alloc from sys.memory_global_by_current_bytes limit 5;
+-------------------------------+---------------+------------+
| event_name | current_alloc | high_alloc |
+-------------------------------+---------------+------------+
| memory/innodb/buf_buf_pool | 10.72 GiB | 10.72 GiB |
| memory/temptable/physical_ram | 514.00 MiB | 515.00 MiB |
| memory/innodb/hash0hash | 292.69 MiB | 292.69 MiB |
| memory/innodb/memory | 191.77 MiB | 197.94 MiB |
| memory/sql/TABLE | 60.39 MiB | 62.35 MiB |
+-------------------------------+---------------+------------+
5 rows in set (0.45 sec)
Nachfolgend finden Sie Details zu den einzelnen Zuweisungstypen.
BOLDZuweisungstypBOLD | Details |
memory/innodb/buf_buf_pool | Von InnoDB-Pufferpool verwendeter Arbeitsspeicher |
memory/temptable/physical_ram | Von internen temporären Tabellen belegter Arbeitsspeicher |
memory/innodb/hash0hash | Von der InnoDB-Hash-Tabelle verwendeter Arbeitsspeicher |
memory/innodb/memory | Von verschiedenen InnoDB-Zwischenspeichern verwendeter Arbeitsspeicher |
memory/sql/TABLE | Von TABLE-Objekten und ihrem Mem-Stamm verwendeter Arbeitsspeicher |
BOLDZuweisungstypBOLD
Details
memory/innodb/buf_buf_pool
Von InnoDB-Pufferpool verwendeter Arbeitsspeicher
memory/temptable/physical_ram
Von internen temporären Tabellen belegter Arbeitsspeicher
memory/innodb/hash0hash
Von der InnoDB-Hash-Tabelle verwendeter Arbeitsspeicher
memory/innodb/memory
Von verschiedenen InnoDB-Zwischenspeichern verwendeter Arbeitsspeicher
memory/sql/TABLE
Von TABLE-Objekten und ihrem Mem-Stamm verwendeter Arbeitsspeicher
Diese Ansicht fasst die Arbeitsspeichernutzung gruppiert nach Nutzer zusammen. Hat ein Nutzer mehrere Verbindungen, wird die Arbeitsspeichernutzung für alle Instanzen des Nutzers addiert.
mysql> select user,current_allocated from memory_by_user_by_current_bytes;
+-----------------+-------------------+
| user | current_allocated |
+-----------------+-------------------+
| sbtest | 60.30 MiB |
| background | 2.68 MiB |
| root | 1.52 MiB |
| event_scheduler | 16.38 KiB |
+-----------------+-------------------+
4 rows in set (1.16 sec)
Wenn Sie für jede Anwendung oder jeden Job einen anderen Nutzer verwenden (empfohlen), kann diese Ansicht dabei helfen, herauszufinden, ob eine bestimmte Anwendung oder ein bestimmter Job viel Arbeitsspeicher verbraucht.
In dieser Ansicht wird die Arbeitsspeichernutzung gruppiert nach Hostnamen zusammengefasst.
mysql> select host,current_allocated from memory_by_host_by_current_bytes;
+------------+-------------------+
| host | current_allocated |
+------------+-------------------+
| 10.128.0.8 | 62.10 MiB |
| background | 2.70 MiB |
| 127.0.0.1 | 311.01 KiB |
| localhost | 16.38 KiB |
+------------+-------------------+
4 rows in set (1.58 sec)
Diese Ansicht ist nützlich, um die Arbeitsspeichernutzung pro Clienthost zu ermitteln. Mehrere Client-/Anwendungsserver sind heutzutage sehr üblich. Mithilfe dieser Ansicht können Sie ermitteln, ob ein bestimmter Client oder eine bestimmte Arbeitslast die Arbeitsspeicherauslastung verursacht. Sie können die Änderung auch zuerst auf einem Client-/Anwendungsserver implementieren, ihre Auswirkungen auf den Arbeitsspeicher überwachen (durch Vergleichen der Arbeitsspeichernutzung mit anderen Client-Hosts) und fundierte Entscheidungen treffen.
Diese Ansicht fasst die Arbeitsspeichernutzung nach Thread gruppiert zusammen und hilft, die Threads zu finden, die den meisten Arbeitsspeicher belegen.
mysql> select thread_id,user,current_allocated from sys.memory_by_thread_by_current_bytes limit 5;
+-----------+-------------------+-------------------+
| thread_id | user | current_allocated |
+-----------+-------------------+-------------------+
| 12999 | sbtest@10.128.0.8 | 3.80 MiB |
| 12888 | sbtest@10.128.0.8 | 3.75 MiB |
| 12760 | sbtest@10.128.0.8 | 3.68 MiB |
| 13128 | sbtest@10.128.0.8 | 3.67 MiB |
| 13221 | sbtest@10.128.0.8 | 3.47 MiB |
+-----------+-------------------+-------------------+
5 rows in set (2.29 sec)
Wenn Sie feststellen, dass ein bestimmter Thread viel Arbeitsspeicher verbraucht, können Sie die langsamen MySQL-Abfragelogs oder die allgemeinen Logs mithilfe der „thread_id“ filtern und die Sitzung/Abfragen identifizieren, die zum Anstieg des Arbeitsspeichers geführt haben.
Die Fehlerbehebung bei hoher Arbeitsspeichernutzung ist eine schwierige Aufgabe. Glücklicherweise hilft die Speicherinstrumentierung performance_schema Nutzern dabei zu verstehen, wie der Speicher von internen MySQL-Strukturen verwendet wird. Die Sys-Schemaansichten erleichtern die Interpretation der Informationen. Wenn speicherbezogene Probleme auftreten, hilft Ihnen diese Funktion, die Ursache des Problems zu finden. Sie können das Problem beheben, indem Sie die Konfigurations-/Abfrageänderungen vornehmen.
Beispiel:
Wenn eine MySQL-Instanz den Arbeitsspeicher höher nutzt als vorgesehen und die Arbeitsspeichernutzung kontinuierlich zunimmt, bis dem Server der Arbeitsspeicher ausgeht, und „performance_schema“ entweder eine Abweichung beim gesamten Arbeitsspeicher im Vergleich zum instrumentierten Arbeitsspeicher anzeigt für was der Speicher verwendet wird, könnte das ein Hinweis auf ein Speicherleck sein. Wenn Sie ein Speicherleck vermuten, können Sie die folgenden Schritte ausführen:
Profitieren Sie von einem Guthaben über 300 $, um Google Cloud und mehr als 20 „Immer kostenlos“-Produkte kennenzulernen.