Cloud SQL per MySQL di Google Cloud è un servizio di database completamente gestito che semplifica la configurazione, la manutenzione, la gestione e l'amministrazione dei database MySQL, PostgreSQL o SQL Server sulla piattaforma Google Cloud. Cloud SQL esegue un numero elevato di database MySQL nel suo parco risorse ed è normale che alcune istanze MySQL consumino molta memoria e si arrestino in modo anomalo a causa di un errore di esaurimento della memoria (OOM). Questo articolo ti aiuterà a risolvere i problemi relativi alla memoria di MySQL.
Una condizione di esaurimento della memoria (OOM) si verifica quando un processo tenta di allocare memoria e ha esito negativo perché il server non ha memoria disponibile. Questo spesso determina l'esecuzione del Linux OOM Killer, un processo utilizzato dal kernel Linux quando la memoria del sistema è molto ridotta che termina il processo del database.
Un arresto anomalo del database a causa di una condizione OOM non è l'ideale, perché il processo del database viene interrotto utilizzando la direttiva SIGKILL, che non permette all'applicazione di arrestarsi normalmente causando i seguenti problemi:
MySQL ha aggiunto la strumentazione della memoria in performance_schema a partire dalla versione 5.7, il che consente di comprendere l'allocazione della memoria MySQL. Questo articolo ti aiuterà a risolvere i problemi relativi alla memoria di MySQL utilizzando performance_schema.
Ogni istanza Cloud SQL è alimentata da una macchina virtuale (VM) in esecuzione su un server Google Cloud host. Ogni VM gestisce il programma di database, come il server MySQL e gli agenti di servizio che forniscono servizi di supporto, come il logging e il monitoraggio. Cloud SQL riserva una parte di memoria per il sistema operativo e gli agenti di servizio, e alloca la memoria rimanente per i programmi di database come mysqld.
La tabella seguente mostra l'allocazione della memoria per il processo mysqld e la configurazione predefinita del pool di buffer InnoDB per ciascun tipo di macchina.
Tipo di macchina | GiB RAM dell'istanza (byte) | Memoria mysqld (GB) | GiB del pool di buffer InnoDB (byte) | Pool di buffer (% di RAM per istanza) | Pool di buffer (% di memoria 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% |
Tipo di macchina
GiB RAM dell'istanza (byte)
Memoria mysqld (GB)
GiB del pool di buffer InnoDB (byte)
Pool di buffer (% di RAM per istanza)
Pool di buffer (% di memoria 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%
Per istanze con 10 GB di RAM e oltre, il processo mysqld è limitato all'utilizzo del 92% della RAM dell'istanza e il pool di buffer InnoDB è configurato nell'intervallo del 75-80% della memoria disponibile per il processo mysqld. Oltre al pool di buffer InnoDB, MySQL alloca diversi buffer e cache per migliorare le prestazioni. Consulta questo articolo per comprendere l'allocazione della memoria in MySQL.
Quando l'utilizzo della memoria mysqld supera il limite configurato del processo mysqld, Linux OOM Killer termina il processo mysqld perché consuma la maggior parte della memoria dell'istanza.
performance_schema è una funzionalità MySQL per il monitoraggio dell'esecuzione del server a un basso livello. Cloud SQL per MySQL consente di abilitare performance_schema sulle istanze con dimensioni RAM pari o superiori a 3 GB. È abilitato per impostazione predefinita nelle istanze con almeno 15 GB di RAM, a partire dalla versione 8.0 di MySQL.
performance_schema è disabilitato per impostazione predefinita per le versioni 5.6 e 5.7 di MySQL; può essere abilitato utilizzando i flag di database.
L'abilitazione di performance_schema comporta un overhead delle prestazioni e implicazioni per la memoria. Per comprendere l'allocazione della memoria, consulta il modello di allocazione della memoria dello schema delle prestazioni.
La strumentazione della memoria performance_schema aiuta a monitorare l'utilizzo della memoria in MySQL. Gli strumenti di memoria hanno nomi nel formato memory/code_area/instrument_name, dove memory/code_area/instrument_name è un valore come memory/code_area/instrument_name o memory/code_area/instrument_name e instrument_name è il dettaglio dello strumento.
MySQL 5.7 abilita alcuni strumenti di memoria per impostazione predefinita, ma non tutti. Per abilitarli, aggiorna la colonna ENABLED della tabella 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 |
+---------+----------+
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)
L'abilitazione degli strumenti di memoria in runtime conteggia solo gli oggetti di memoria creati dopo l'abilitazione della strumentazione. Pertanto, consigliamo di attendere che il server raccolga dati sufficienti per la risoluzione dei problemi.
MySQL 8.0 abilita tutti gli strumenti di memoria per impostazione predefinita.
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)
Lo schema sys contiene molte visualizzazioni che riassumono i dati di performance_schema in moduli facilmente comprensibili. La maggior parte di queste visualizzazioni è a coppie, in cui entrambe hanno lo stesso nome a cui viene aggiunto il prefisso x$ a una. Le seguenti viste sono disponibili in MySQL 5.7 e 8.0 per visualizzare l'allocazione della memoria a diversi livelli.
mysql> use sys;
Database changed
mysql> show tables like '%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 visualizzazione sys.memory_global_total riassume l'utilizzo totale della memoria in un formato leggibile.
mysql> select * from sys.memory_global_total;
+-----------------+
| total_allocated |
+-----------------+
| 12.43 GiB |
+-----------------+
1 row in set (0.44 sec)
Il parametro sys.x$memory_global_total mostra le stesse informazioni, ma in byte.
mysql> select * from sys.x$memory_global_total;
+-----------------+
| total_allocated |
+-----------------+
| 13351482992 |
+-----------------+
1 row in set (1.39 sec)
La visualizzazione senza il prefisso x$ ha lo scopo di fornire un output più facile da usare e da leggere. La visualizzazione con il prefisso x$ che mostra gli stessi valori in formato non elaborato è destinata principalmente all'utilizzo con altri strumenti che eseguono la propria elaborazione sui dati.
La vista sys.memory_global_by_current_bytes mostra l'utilizzo attuale della memoria raggruppato per tipo di allocazione (event_name), ad esempio memory/innodb/buf_buf_pool (pool di buffer InnoDB). Per impostazione predefinita, le righe vengono ordinate in ordine decrescente in base alla quantità di memoria utilizzata.
Prima di esaminare in dettaglio ogni tipo di allocazione, è utile avere una panoramica dell'utilizzo della memoria per ogni area di codice, ad esempio Innodb, sql, performance_schema e altre.
La seguente query aggrega la memoria attualmente allocata per area di codice.
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)
Questo output mostra che innodb utilizza la maggior parte della memoria, seguito da performance_schema e dalle tabelle temporanee.
Ora, l'esecuzione di una query su sys.memory_global_by_current_bytes mostra direttamente l'utilizzo della memoria per le strutture interne di MySQL, come descritto nella colonna event_name. Se stai cercando di risolvere i problemi relativi a un aumento anomalo della memoria, puoi identificare l'origine osservando l'output di questa visualizzazione.
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)
Di seguito sono riportati i dettagli di ciascun tipo di allocazione.
Tipo di allocazione | Dettagli |
memory/innodb/buf_buf_pool | Memoria utilizzata dal pool di buffer InnoDB |
memory/temptable/physical_ram | Memoria utilizzata da tabelle temporanee interne |
memory/innodb/hash0hash | Memoria utilizzata dalla tabella hash InnoDB |
memory/innodb/memory | Memoria utilizzata da vari buffer InnoDB |
memory/sql/TABLE | Memoria utilizzata dagli oggetti TABLE e dalla relativa root mem |
Tipo di allocazione
Dettagli
memory/innodb/buf_buf_pool
Memoria utilizzata dal pool di buffer InnoDB
memory/temptable/physical_ram
Memoria utilizzata da tabelle temporanee interne
memory/innodb/hash0hash
Memoria utilizzata dalla tabella hash InnoDB
memory/innodb/memory
Memoria utilizzata da vari buffer InnoDB
memory/sql/TABLE
Memoria utilizzata dagli oggetti TABLE e dalla relativa root mem
Questa visualizzazione riassume l'utilizzo della memoria raggruppato per utente. Se un utente ha più connessioni, somma la memoria utilizzata per tutte le istanze dell'utente.
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)
Se utilizzi un utente diverso per ogni applicazione/lavoro (opzione consigliata), questa visualizzazione può aiutarti a identificare se una determinata applicazione o job consuma molta memoria.
Questa visualizzazione riassume la memoria utilizzata raggruppata per nome host.
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)
Questa visualizzazione è utile per identificare l'utilizzo della memoria per host client. È molto comune al giorno d'oggi avere più server client/delle applicazioni, per cui questa visualizzazione ti aiuterà a identificare se un particolare client o carico di lavoro sta causando un elevato utilizzo della memoria. Puoi anche eseguire il deployment della modifica su un solo client/server delle applicazioni, monitorarne l'impatto sulla memoria (confrontando l'utilizzo della memoria con quello di altri host client) e prendere decisioni consapevoli.
Questa visualizzazione riassume l'utilizzo della memoria raggruppato per thread. È utile per trovare i thread che occupano la maggior parte della memoria.
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)
Se scopri che un determinato thread consuma molta memoria, puoi filtrare i log delle query MySQL lente o i log generali utilizzando thread_id e identificare le sessioni/query che hanno portato all'aumento della memoria.
La risoluzione dei problemi relativi a un utilizzo elevato di memoria è un'attività impegnativa. Per fortuna, la strumentazione della memoria performance_schema aiuta gli utenti a capire in che modo la memoria viene utilizzata dalle strutture MySQL interne. Le visualizzazioni dello schema sys semplificano l'interpretazione delle informazioni. Se riscontri problemi relativi alla memoria, questa funzionalità ti aiuterà a trovarne l'origine e potrai correggerli apportando modifiche alla configurazione/alla query.
Ad esempio:
Se ti imbatti in una situazione in cui un'istanza MySQL utilizza più memoria del dovuto e l'utilizzo della memoria aumenta continuamente fino a quando il server non esaurisce la memoria e performance_schema mostra un divario tra memoria totale e memoria instrumentata o non segnala dove sta andando la memoria, potrebbe indicare una perdita di memoria. Se sospetti che si sia verificata una perdita di memoria, puoi procedere nel seguente modo:
Inizia a creare su Google Cloud con 300 $ di crediti gratuiti e oltre 20 prodotti Always Free.