L'elevato utilizzo della CPU in un'istanza può essere causato da vari motivi come l'aumento dei carichi di lavoro, transazioni complesse, query lente e transazioni a lunga esecuzione.
Il motore per suggerimenti di istanze sottodimensionate analizza l'utilizzo della CPU. Se i livelli di utilizzo della CPU raggiungono o superano il 95% per un periodo di tempo significativo negli ultimi 30 giorni, il recommender ti avvisa e fornisce approfondimenti aggiuntivi per aiutarti a risolvere il problema.
Questo documento spiega come rivedere e ottimizzare un'istanza Cloud SQL per MySQL se questa viene identificata dal motore per suggerimenti delle istanze con underprovisioning in quanto ha un utilizzo elevato della CPU.
Consigli
L'utilizzo della CPU aumenta proporzionalmente al carico di lavoro. Per ridurre l'utilizzo della CPU, controlla le query in esecuzione e ottimizzale. Di seguito sono riportati alcuni passaggi per controllare il consumo della CPU.
Controlla
Threads_running
eThreads_connected
Utilizza la seguente query per visualizzare il numero di thread attivi:
> SHOW STATUS like 'Threads_%';
Threads_running
è un sottoinsieme diThreads_connected
. Il resto dei thread è inattivo. Un aumento diThreads_running
contribuirebbe a un aumento dell'utilizzo della CPU. È una buona idea controllare cosa viene eseguito in questi thread.Controlla gli stati delle query
Esegui il comando
SHOW PROCESSLIST
per visualizzare le query in corso. Restituisce tutti i thread collegati in ordine e l'istruzione SQL attualmente in esecuzione.mysql> SHOW [FULL] PROCESSLIST;
Presta attenzione alle colonne Stato e Durata. Controlla se sono presenti molte query bloccate sullo stesso stato.
- Se molti thread mostrano
Updating
, potrebbe esserci un conflitto di blocco del record. Vedi il passaggio successivo. - Se molti thread mostrano
Waiting
per il blocco dei metadati della tabella, controlla la query per conoscere la tabella, quindi cerca un DDL (ad esempioALTER TABLE
) che potrebbe contenere il blocco dei metadati. Un DDL potrebbe anche essere in attesa del blocco dei metadati della tabella se una query precedente, ad esempio unSELECT query
a lunga esecuzione, lo sta mantenendo.
- Se molti thread mostrano
Verifica la contesa per il blocco dei record
Quando le transazioni detengono i blocchi sui record degli indici più utilizzati, bloccano altre transazioni che richiedono gli stessi blocchi. Ciò potrebbe causare un effetto a catena e bloccare un numero di richieste, con un aumento del valore di
Threads_running
. Per diagnosticare la contesa dei blocchi, utilizza la tabellainformation_schema.innodb_lock_waits
.La seguente query elenca ogni transazione di blocco e il numero di transazioni bloccate associate.
SELECT t.trx_id, t.trx_state, t.trx_started, COUNT(distinct w.requesting_trx_id) AS blocked_trxs FROM information_schema.innodb_lock_waits w INNER JOIN information_schema.innodb_trx t ON t.trx_id = w.blocking_trx_id GROUP BY t.trx_id,t.trx_state, t.trx_started ORDER BY t.trx_id;
Sia un'unica DML di grandi dimensioni sia molte DML di piccole dimensioni concorrenti potrebbero causare conflitti di blocco delle righe. Per ottimizzare questo aspetto dal lato dell'applicazione, segui questi passaggi:
- Evita transazioni lunghe perché i blocchi delle righe vengono mantenuti fino al termine della transazione.
- Suddividi un'unica DML di grandi dimensioni in DML più piccole.
- Raggruppa in piccoli blocchi un DML di una singola riga.
- Ridurre al minimo i conflitti tra i thread; Ad esempio, se il codice dell'applicazione usa un pool di connessioni, assegnare un intervallo di ID allo stesso thread.
Trovare transazioni a lunga esecuzione
Utilizza
SHOW ENGINE INNODB STATUS
Nella sezione TRANSAZIONI, puoi vedere tutte le transazioni aperte ordinate dal più recente al meno recente.
mysql> SHOW ENGINE INNODB STATUS\G …… ------------ TRANSACTIONS ------------ … ---TRANSACTION 245762, ACTIVE 262 sec 2 lock struct(s), heap size 1136, 1 row lock(s), undo log entries 1 MySQL thread id 9210, OS thread handle 140262286128896, query id 202218 localhost root
Inizia con le transazioni più vecchie e trova le risposte alle seguenti domande:
- Da quanto tempo sono in esecuzione queste transazioni?
- Quanti blocchi struct e righe sono presenti?
- Quante voci di log di annullamento sono presenti?
- Cosa sono gli host e gli utenti che si connettono?
- Qual è l'istruzione SQL in corso?
Utilizza
information_schema.innodb_trx
Se
SHOW ENGINE INNODB STATUS
è stato troncato, un modo alternativo per esaminare tutte le transazioni aperte è utilizza la tabellainformation_schema.innodb_trx
:SELECT trx_id, trx_state, timestampdiff(second, trx_started, now()) AS active_secs, timestampdiff(second, trx_wait_started, now()) AS wait_secs, trx_tables_in_use, trx_tables_locked, trx_lock_structs, trx_rows_locked, trx_rows_modified, trx_query FROM information_schema.innodb_trx
Se le transazioni mostrano le attuali istruzioni a lunga esecuzione, puoi decidere di interromperle per ridurre la pressione sul server o attendere il completamento delle transazioni più importanti. Se le transazioni precedenti non mostrano alcuna attività, vai al passaggio successivo per trovare la cronologia transazioni.
Controllare le istruzioni SQL delle transazioni a lunga esecuzione
Utilizza
performance_schema
Per usare la funzionalità
performance_schema
, devi prima attivarla. È una modifica che richiede il riavvio dell'istanza. Dopo aver attivatoperformance_schema
, controlla che gli strumenti e i consumer siano abilitati:SELECT * FROM setup_consumers where name like 'events_statements_history'; SELECT * FROM setup_instruments where name like 'statement/sql/%';
Se non sono attivati, attivali:
UPDATE setup_instruments SET ENABLED = 'YES', timed = 'YES' WHERE NAME LIKE 'statement/%'; UPDATE setup_consumers SET ENABLED = 'YES' WHERE NAME LIKE 'events_statements%';
Per impostazione predefinita, ogni thread conserva gli ultimi 10 eventi definiti da
performance_schema_events_statements_history_size
. In genere sono sufficienti per individuare la transazione nel codice dell'applicazione. Questo parametro non è dinamico.Con
mysql thread id
, che èprocesslist_id
, esegui query sugli eventi della cronologia:SELECT t.thread_id, event_name, sql_text, rows_affected, rows_examined, processlist_id, processlist_time, processlist_state FROM events_statements_history h INNER JOIN threads t ON h.thread_id = t.thread_id WHERE processlist_id = <mysql thread id> ORDER BY event_id;
Utilizzare il log delle query lente
Per il debug, puoi acquisire tutte le query che hanno richiesto più di
N
secondi nel log delle query lente. Puoi attivare i log delle query lente modificando le impostazioni dell'istanza nella pagina dell'istanza della console Google Cloud o digcloud CLI
e poi visualizzare i log utilizzando il visualizzatore dei log nella console Google Cloud o ingloud CLI
.
Controlla la contesa dei semafori
In un ambiente concorrente, i mutex e i latch di lettura/scrittura sulle risorse condivise potrebbero essere il punto di contesa, rallentando le prestazioni del server. Inoltre, se il tempo di attesa del semaforo è superiore a 600 secondi, il sistema può arrestarsi in modo anomalo per uscire dalla situazione di stallo.
Per visualizzare la contesa del semiforo, utilizza il seguente comando:
mysql> SHOW ENGINE INNODB STATUS\G ---------- SEMAPHORES ---------- ... --Thread 140396021667584 has waited at row0purge.cc line 862 for 241.00 seconds the semaphore: S-lock on RW-latch at 0x30c03e8 created in file dict0dict.cc line 1183 a writer (thread id 140395996489472) has reserved it in mode exclusive number of readers 0, waiters flag 1, lock_word: 0 Last time read locked in file row0purge.cc line 862 Last time write locked in file /build/mysql-5.7-FFKPr6/mysql-5.7-5.7.22/storage/innobase/dict/dict0stats.cc line 2376 ...
Ad ogni attesa di un semaforo, la prima riga mostra il thread in attesa, il semaforo specifico e il tempo di attesa. Se si verificano frequenti tempi di attesa durante l'esecuzione ripetuta di
SHOW ENGINE INNODB STATUS
, in particolare per alcuni secondi, significa che nel sistema si stanno verificando colli di bottiglia relativi alla contemporaneità.Esistono punti di contesa diversi in configurazioni e carichi di lavoro diversi.
Quando i semiconduttori sono spesso su btr0sea.c, l'indicizzazione ad hash adattiva potrebbe essere la fonte della contesa. Prova a disabilitarlo utilizzando la console Google Cloud o
gcloud CLI
.Ottimizzare le query
SELECT
lungheInnanzitutto, rivedi la query. Identifica l'obiettivo della query e il modo migliore per ottenere i risultati. Il piano di query migliore è quello che minimizza l'accesso ai dati.
- Controlla il piano di esecuzione della query:
mysql> EXPLAIN <the query>;
Per informazioni su come interpretare l'output e valutare l'efficienza della query, consulta la documentazione di MySQL.
- Utilizza l'indice corretto
Controlla la colonna delle chiavi per verificare se viene utilizzato l'indice previsto. In caso contrario, aggiorna le statistiche dell'indice:
mysql> analyze table <table_name>
Aumenta il numero di pagine di esempio utilizzate per calcolare le statistiche dell'indice. Per saperne di più, consulta la documentazione di MySQL.
- Sfrutta al meglio l'indice
Quando utilizzi un indice a più colonne, controlla le colonne
key_len
per verificare se l'indice viene sfruttato completamente per filtrare i record. Le colonne più a sinistra devono essere confronti uguali e l'indice può essere utilizzato fino alla prima condizione di intervallo inclusa.- Utilizza i suggerimenti di ottimizzazione
Un altro modo per assicurarti l'indice corretto è utilizzare l'indice di suggerimento e l'suggerimento per l'ordine di unione delle tabelle.
Evita un lungo elenco di cronologie con READ COMMITTED
L'elenco della cronologia è l'elenco delle transazioni non eliminate nel tablespace di annullamento. Il livello di isolamento predefinito di una transazione è REPEATABLE READ, che richiede che una transazione legga lo stesso snapshot per tutta la sua durata. Di conseguenza, una query
SELECT
blocca l'eliminazione definitiva dei record del log di annullamento creati dall'inizio della query (o della transazione). Un elenco di cronologia lungo rallenta quindi le prestazioni delle query. Un modo per evitare di creare un elenco di cronologia lungo è modificare il livello di isolamento delle transazioni in LETTURA ACCONTATA. Con READ COMMITTED, non è più necessario conservare l'elenco della cronologia per una visualizzazione di lettura coerente. Puoi modificare il livello di isolamento delle transazioni a livello globale per tutte le sessioni, per una singola sessione o per la successiva singola transazione. Per saperne di più, consulta la documentazione di MySQL.Ottimizzare la configurazione del server
C'è molto da dire sulla configurazione del server. Sebbene la storia completa non rientri nell'ambito di questo documento, vale la pena ricordare che il server segnala anche variabili di stato che forniscono suggerimenti sull'efficacia delle configurazioni correlate. Ad esempio:
- Regola
thread_cache_size
seThreads_created/Connections
è grande. Una cache dei thread adeguata ridurrebbe il tempo di creazione dei thread e agevolerebbe il carico di lavoro altamente concorrente. - Modifica
table_open_cache
seTable_open_cache_misses/Table_open_cache_hits
non è banale. La presenza di tabelle nella cache delle tabelle salva tempi di esecuzione delle query e questo potrebbe fare la differenza in un ambiente altamente simultaneo.
- Regola
Terminare una connessione indesiderata
Puoi interrompere la query se sembra non valida o non è più richiesta. Per scoprire come identificare e terminare il thread MySQL, consulta Gestire le connessioni di database.
Infine, se l'utilizzo della CPU è ancora elevato e le query generano il traffico necessario, ti consigliamo di aumentare le risorse della CPU nell'istanza per evitare arresti anomali o tempi di riposo del database.