Cloud SQL pour MySQL est un service de base de données entièrement géré qui vous aide à configurer, entretenir, gérer et administrer votre base de données MySQL, PostgreSQL ou SQL Server sur Google Cloud Platform. Cloud SQL exécute un grand nombre de bases de données MySQL dans son parc. Il est donc fréquent que certaines instances MySQL consomment beaucoup de mémoire et plantent en raison d'une erreur de mémoire saturée (OOM, Out Of Memory). Cet article vous aidera à résoudre les problèmes de mémoire MySQL.
Une condition de mémoire insuffisante (OOM) se produit lorsqu'un processus tente d'allouer de la mémoire et échoue, car le serveur n'a plus de mémoire disponible. Cela se traduit souvent par l'exécution du Killer Linux OOM, un processus utilisé par le noyau Linux lorsque le système est très insuffisant en mémoire, ce qui met fin au processus de base de données.
Un plantage de base de données dû à une condition OOM n'est pas idéal, car le processus de base de données est arrêté à l'aide de la directive SIGKILL, ce qui empêche l'application d'arrêter normalement MySQL. Cela entraîne les problèmes suivants :
MySQL a ajouté une instrumentation de mémoire dans performance_schema à partir de la version 5.7, ce qui permet de mieux comprendre l'allocation de mémoire MySQL. Cet article vous aidera à résoudre les problèmes de mémoire MySQL à l'aide de performance_schema.
Chaque instance Cloud SQL est alimentée par une machine virtuelle (VM) exécutée sur un serveur hôte Google Cloud. Chaque VM exploite le programme de base de données, tel que le serveur MySQL et les agents de service qui fournissent des services complémentaires, tels que la journalisation et la surveillance. Cloud SQL réserve une partie de la mémoire pour le système d'exploitation (OS) et les agents de service, et alloue la mémoire restante aux programmes de base de données tels que mysqld.
Le tableau suivant indique l'allocation de mémoire pour le processus mysqld et la configuration par défaut du pool de mémoire tampon InnoDB pour chaque type de machine.
Type de machine |
GIB de RAM de l'instance (octets) |
Mémoire mysqld (Go) |
Pool de mémoire tampon InnoDB, en Gio (octets) |
Pool de mémoire tampon (% de RAM de l'instance) |
Pool de mémoire tampon (% de mémoire mysqld) |
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 % |
Pour les instances disposant d'au moins 10 Go de RAM, le processus mysqld est limité à 92% de la RAM de l'instance, et le pool de mémoire tampon InnoDB est configuré entre 75 et 80% de la mémoire disponible pour le processus mysqld. En plus du pool de mémoire tampon InnoDB, MySQL alloue plusieurs tampons et caches pour améliorer les performances. Veuillez consulter cet article pour en savoir plus sur l'allocation de mémoire dans MySQL.
Lorsque l'utilisation de la mémoire mysqld dépasse la limite configurée du processus mysqld, le tueur OOM Linux ferme le processus mysqld, car il s'agit du plus grand consommateur de mémoire de l'instance.
performance_schema est une fonctionnalité MySQL permettant de surveiller l'exécution des serveurs à un niveau inférieur. Cloud SQL pour MySQL permet d'activer performance_schema sur les instances dont la taille de RAM est supérieure ou égale à 3 Go. Elle est activée par défaut dans les instances disposant d'au moins 15 Go de RAM, à partir de la version MySQL 8.0.
Performance_schema est désactivée par défaut pour les versions 5.6 et 5.7 de MySQL. Vous pouvez l'activer à l'aide des options de base de données.
L'activation de performance_schema entraîne une surcharge des performances et des conséquences sur la mémoire. Consultez la section sur le modèle d'allocation de mémoire du schéma de performances pour comprendre son allocation de mémoire.
L'instrumentation de mémoire performance_schema permet de surveiller l'utilisation de la mémoire dans MySQL. Les outils liés à la mémoire ont des noms ayant la forme mémoire/zone_code/nom_instrument , où zone_code est une valeur telle que SQL ou Innodb et nom_instrument correspond au détail de l'instrument.
MySQL 5.7 active certains outils liés à la mémoire par défaut, mais pas tous. Vous pouvez les activer en mettant à jour la colonne ENABLED de la table performance_schema.setup_instruments.
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 |
+---------+----------+
1186 rows in set (0.03 sec)
mysql> UPDATE performance_schema.setup_instruments SET ENABLED = 'YES' WHERE NAME LIKE 'memory/%';
Query OK, 306 rows affected (0.00 sec)
Lignes correspondantes : 376 Modifiées : 306 Avertissements : 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)
Si vous activez les instruments de mémoire au moment de l'exécution, seuls les objets mémoire créés après l'activation de l'instrumentation sont pris en compte. Par conséquent, nous vous recommandons d'attendre que le serveur collecte suffisamment de données à des fins de dépannage.
MySQL 8.0 active tous les instruments de mémoire par défaut.
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)
Le schéma système contient de nombreuses vues qui résument les données performance_schema dans des formes facilement compréhensibles. La plupart de ces vues sont présentées par paire. Elles portent le même nom et l'une d'entre elles a le préfixe x$. Les vues suivantes sont disponibles dans MySQL 5.7 et 8.0 pour afficher l'allocation de mémoire à différents niveaux.
mysql> utilise sys;
Base de données modifiée
mysql> affiche des tables telles que "%memory%';
+-------------------------------------+
| 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)
La vue sys.memory_global_total résume l'utilisation totale de la mémoire dans un format lisible.
mysql> select * from sys.memory_global_total;
+-----------------+
| total_allocated |
+-----------------+
| 12.43 GiB |
+-----------------+
1 row in set (0.44 sec)
sys.x$memory_global_total affiche les mêmes informations, mais en octets.
mysql> select * from sys.x$memory_global_total;
+-----------------+
| total_allocated |
+-----------------+
| 13351482992 |
+-----------------+
1 row in set (1.39 sec)
L'affichage sans le préfixe x$ est destiné à fournir une sortie plus conviviale et plus lisible. La vue avec le préfixe x$ qui affiche les mêmes valeurs au format brut est davantage destinée à être utilisée avec d'autres outils qui effectuent leur propre traitement des données.
La vue sys.memory_global_by_current_bytes indique l'utilisation actuelle de la mémoire, regroupée par type d'allocation (event_name), par exemple "memory/innodb/buf_buf_pool" (pool de mémoire tampon InnoDB). Par défaut, les lignes sont triées par ordre décroissant de la quantité de mémoire utilisée.
Avant d'explorer chaque type d'allocation, il est utile d'avoir un aperçu de l'utilisation de la mémoire pour chaque zone de code, comme Innodb, sql, performance_schema, etc.
La requête suivante agrège la mémoire actuellement allouée par zone de code.
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 bytes |
| memory/csv | 88 bytes |
| memory/blackhole | 88 bytes |
+---------------------------+---------------+
9 rows in set (1.02 sec)
Ce résultat montre qu'innodb est le plus grand consommateur de mémoire, suivi de performance_schema et des tables temporaires.
Désormais, l'interrogation de sys.memory_global_by_current_bytes affiche directement l'utilisation de la mémoire pour les structures internes MySQL, comme décrit dans la colonne event_name. Si vous tentez de résoudre les problèmes d'augmentation anormale de la mémoire, vous pouvez identifier la source en examinant le résultat de cette vue.
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)
Vous trouverez ci-dessous les détails de chaque type d'allocation.
Type d'allocation |
Détails |
memory/innodb/buf_buf_pool |
Mémoire utilisée par le pool de mémoire tampon InnoDB |
memory/temptable/physical_ram |
Mémoire utilisée par les tables temporaires internes |
memory/innodb/hash0hash |
Mémoire utilisée par la table de hachage InnoDB |
memory/innodb/memory |
Mémoire utilisée par différents tampons InnoDB |
memory/sql/TABLE |
Mémoire utilisée par les objets TABLE et leur racine mem |
Cette vue récapitule l'utilisation de la mémoire regroupée par utilisateur. Si un utilisateur dispose de plusieurs connexions, elle additionne l'utilisation de la mémoire pour toutes les instances de l'utilisateur.
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)
Si vous utilisez un utilisateur différent pour chaque application ou tâche (recommandé), cette vue peut vous aider à déterminer si une application ou une tâche en particulier consomme beaucoup de mémoire.
Cette vue récapitule l'utilisation de mémoire regroupée par nom d'hôte.
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)
Cette vue est utile pour identifier l'utilisation de la mémoire par hôte client. De nos jours, il est très fréquent d'avoir plusieurs serveurs clients/applications. Grâce à cette vue, vous pouvez déterminer si un client ou une charge de travail spécifiques sont à l'origine d'une utilisation intensive de la mémoire. Vous pouvez également commencer par déployer le changement sur un client/serveur d'applications, surveiller son impact sur la mémoire (en comparant l'utilisation de la mémoire à celle d'autres hôtes clients) et prendre des décisions éclairées.
Cette vue récapitule l'utilisation de la mémoire, regroupée par thread. Elle permet de trouver les threads qui utilisent la plus grande partie de la mémoire.
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)
Si vous constatez qu'un thread particulier consomme beaucoup de mémoire, vous pouvez filtrer les journaux des requêtes lentes MySQL ou les journaux généraux à l'aide de thread_id et identifier la ou les sessions/requêtes qui ont entraîné la croissance de la mémoire.
Le dépannage d'une utilisation de mémoire élevée n'est pas une mince affaire. Heureusement, l'instrumentation de mémoire performance_schema aide les utilisateurs à comprendre comment les structures MySQL internes utilisent la mémoire. Les vues de schéma système facilitent l'interprétation des informations. Si vous rencontrez des problèmes liés à la mémoire, cette fonctionnalité vous aidera à trouver la source du problème, et vous pourrez y remédier en modifiant la configuration/requête.
Par exemple :
Imaginons qu'une instance MySQL utilise une quantité de mémoire supérieure à ce qu'elle devrait et que cette utilisation augmente continuellement jusqu'à ce que le serveur soit à court de mémoire. Dans ce cas, le champ performance_schema affiche un écart entre la mémoire totale et la mémoire instrumentée ou ne vous indique pas où va la mémoire, ce qui pourrait être le signe d'une fuite de mémoire. Si vous suspectez une fuite de mémoire, vous pouvez prendre les mesures suivantes :
Profitez de 300 $ de crédits gratuits et de plus de 20 produits Always Free pour commencer à créer des applications sur Google Cloud.