Dela via


Felsöka hög CPU-användning i Azure Database for MySQL – flexibel server

GÄLLER FÖR: Azure Database for MySQL – Azure Database for MySQL – enskild server – flexibel server

Viktigt!

Azure Database for MySQL – enskild server är på väg att dras tillbaka. Vi rekommenderar starkt att du uppgraderar till en flexibel Azure Database for MySQL-server. Mer information om hur du migrerar till en flexibel Azure Database for MySQL-server finns i Vad händer med Azure Database for MySQL – enskild server?

Azure Database for MySQL – flexibel server innehåller ett antal mått som du kan använda för att identifiera resursflaskhalsar och prestandaproblem på servern. För att avgöra om servern har hög CPU-användning övervakar du mått som "Processorprocent för värd", "Totalt antal anslutningar", "Värdminnesprocent" och "I/O-procent". Ibland ger visning av en kombination av dessa mått insikter om vad som kan orsaka den ökade CPU-användningen på din flexibla Serverinstans i Azure Database for MySQL.

Överväg till exempel en plötslig ökning av anslutningar som initierar en våg av databasfrågor som gör att CPU-användningen skjuts upp.

Förutom att samla in mått är det viktigt att även spåra arbetsbelastningen för att förstå om en eller flera frågor orsakar toppar i CPU-användningen.

Hög CPU-orsaker

Cpu-toppar kan inträffa av olika orsaker, främst på grund av toppar i anslutningar och dåligt skrivna SQL-frågor, eller en kombination av båda:

Ökning av anslutningar

En ökning av anslutningar kan leda till en ökning av trådar, vilket i sin tur kan orsaka en ökning av processoranvändning eftersom den måste hantera dessa anslutningar tillsammans med deras frågor och resurser. Om du vill felsöka en topp i anslutningar bör du kontrollera måttet Totalt antal anslutningar och gå till nästa avsnitt för mer information om dessa anslutningar. Du kan använda performance_schema för att identifiera de värdar och användare som för närvarande är anslutna till servern med följande kommandon:

Aktuella anslutna värdar

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

Aktuella anslutna användare

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

Dåligt skrivna SQL-frågor

Frågor som är dyra att köra och skanna ett stort antal rader utan index, eller de som utför tillfälliga sorteringar tillsammans med andra ineffektiva planer, kan leda till CPU-toppar. Vissa frågor kan köras snabbt i en enda session, men de kan orsaka CPU-toppar när de körs i flera sessioner. Därför är det viktigt att alltid förklara dina frågor som du samlar in från visningsprocesslistan och se till att deras körningsplaner är effektiva. Detta kan uppnås genom att säkerställa att de genomsöker ett minimalt antal rader med hjälp av filter/where-satsen, använder index och undviker att använda stor tillfällig sortering tillsammans med andra felaktiga körningsplaner. Mer information om körningsplaner finns i FÖRKLARA utdataformat.

Samla in information om den aktuella arbetsbelastningen

Kommandot SHOW (FULL) PROCESSLIST visar en lista över alla användarsessioner som för närvarande är anslutna till azure database for MySQL– flexibel serverinstans. Den innehåller också information om det aktuella tillståndet och aktiviteten för varje session.

Det här kommandot genererar endast en ögonblicksbild av den aktuella sessionsstatusen och ger inte information om historisk sessionsaktivitet.

Nu ska vi ta en titt på exempelutdata från att köra det här kommandot.

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)

Observera att det finns två sessioner som ägs av den kundägda användaren "adminuser", båda från samma IP-adress:

  • Session 24835 har kört en SELECT-instruktion under de senaste sju sekunderna.
  • Session 24837 kör instruktionen "visa fullständig processlista".

Vid behov kan det krävas att en fråga avslutas, till exempel en rapporteringsfråga eller en HTAP-fråga som har gjort att processoranvändningen för produktionsarbetsbelastningen har ökat. Tänk dock alltid på de potentiella konsekvenserna av att avsluta en fråga innan du vidtar åtgärden i ett försök att minska CPU-användningen. Andra gånger om det finns långvariga frågor som identifieras som leder till CPU-toppar justerar du dessa frågor så att resurserna utnyttjas optimalt.

Detaljerad aktuell arbetsbelastningsanalys

Du måste använda minst två informationskällor för att få korrekt information om status för en session, transaktion och fråga:

  • Serverns processlista från INFORMATION_SCHEMA. PROCESSLIST-tabell, som du också kan komma åt genom att köra kommandot SHOW [FULL] PROCESSLIST.
  • InnoDB:s transaktionsmetadata från INFORMATION_SCHEMA. INNODB_TRX tabell.

Med information från endast en av dessa källor är det omöjligt att beskriva anslutnings- och transaktionstillståndet. Processlistan informerar dig till exempel inte om det finns en öppen transaktion som är associerad med någon av sessionerna. Å andra sidan visar transaktionsmetadata inte sessionstillstånd och tid i det tillståndet.

Följande exempelfråga som kombinerar processlistinformation med några av de viktiga delarna i InnoDB-transaktionsmetadata:

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

I följande exempel visas utdata från den här frågan:

*************************** 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

En analys av den här informationen, efter session, visas i följande tabell.

Ytdiagram Analys
Session 11 Den här sessionen är för närvarande inaktiv (i viloläge) utan att några frågor körs, och den har varit i 636 sekunder. I sessionen har en transaktion som varit öppen i 2908 sekunder ändrat 17 825 792 rader och använder REPEATABLE READ-isolering.
Session 12 Sessionen kör för närvarande en SELECT-instruktion som har körts i 15 sekunder. Det finns ingen fråga som körs i sessionen, vilket anges av NULL-värdena för trx_started och trx_age_seconds. Sessionen fortsätter att hålla skräpinsamlingsgränsen så länge den körs om den inte använder den mer avslappnade READ COMMITTED-isoleringen.

Observera att om en session rapporteras som inaktiv kör den inte längre några instruktioner. Nu har sessionen slutfört allt tidigare arbete och väntar på nya instruktioner från klienten. Inaktiva sessioner ansvarar dock fortfarande för viss cpu-förbrukning och minnesanvändning.

Visa en lista över öppna transaktioner

Utdata från följande fråga innehåller en lista över alla transaktioner som för närvarande körs mot databasservern i ordning efter transaktionsstarttid så att du enkelt kan identifiera om det finns några tidskrävande och blockerande transaktioner som överskrider deras förväntade körning.

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;

Förstå trådtillstånd

Transaktioner som bidrar till högre CPU-användning under körningen kan ha trådar i olika tillstånd, enligt beskrivningen i följande avsnitt. Använd den här informationen för att bättre förstå frågelivscykeln och olika trådtillstånd.

Kontrollera behörigheter/Öppna tabeller

Det här tillståndet innebär vanligtvis att den öppna tabellåtgärden tar lång tid. Vanligtvis kan du öka tabellens cachestorlek för att förbättra problemet. Men tabeller som öppnas långsamt kan också tyda på andra problem, till exempel att ha för många tabeller under samma databas.

Skicka data

Även om det här tillståndet kan innebära att tråden skickar data via nätverket, kan det också indikera att frågan läser data från disken eller minnet. Det här tillståndet kan orsakas av en sekventiell tabellgenomsökning. Du bör kontrollera värdena för innodb_buffer_pool_reads och innodb_buffer_pool_read_requests för att avgöra om ett stort antal sidor hanteras från disken till minnet. Mer information finns i Felsöka problem med lite minne i Azure Database for MySQL – flexibel server.

Uppdatera

Det här tillståndet innebär vanligtvis att tråden utför en skrivåtgärd. Kontrollera det I/O-relaterade måttet i Prestandaövervakaren för att få en bättre förståelse för vad de aktuella sessionerna gör.

Väntar <på lock_type> lås

Det här tillståndet anger att tråden väntar på ett andra lås. I de flesta fall kan det vara ett metadatalås. Du bör granska alla andra trådar och se vem som tar låset.

Förstå och analysera väntehändelser

Det är viktigt att förstå de underliggande väntehändelserna i MySQL-motorn, eftersom långa väntetider eller ett stort antal väntetider i en databas kan leda till ökad processoranvändning. I följande exempel visas lämpligt kommando och exempelutdata.

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)

Begränsa körningstiden för SELECT-instruktioner

Om du inte känner till körningskostnaden och körningstiden för databasåtgärder som involverar SELECT-frågor kan eventuella långvariga SELECT-filer leda till oförutsägbarhet eller volatilitet på databasservern. Storleken på instruktioner och transaktioner samt den associerade resursanvändningen fortsätter att växa beroende på den underliggande datamängdens tillväxt. På grund av denna obundna tillväxt tar slutanvändarinstruktioner och transaktioner längre och längre, vilket förbrukar allt mer resurser tills de överbelastar databasservern. När du använder obundna SELECT-frågor rekommenderar vi att du konfigurerar parametern max_execution_time så att alla frågor som överskrider den här varaktigheten avbryts.

Rekommendationer

  • Kontrollera att databasen har tillräckligt med resurser allokerade för att köra dina frågor. Ibland kan du behöva skala upp instansstorleken för att få fler processorkärnor för att hantera din arbetsbelastning.
  • Undvik stora eller långvariga transaktioner genom att dela upp dem i mindre transaktioner.
  • Kör SELECT-instruktioner på läsreplikservrar när det är möjligt.
  • Använd aviseringar på "Host CPU Percent" så att du får meddelanden om systemet överskrider något av de angivna tröskelvärdena.
  • Använd Query Performance Insights eller Azure-arbetsböcker för att identifiera eventuella problematiska eller långsamt körande frågor och sedan optimera dem.
  • För produktionsdatabasservrar samlar du in diagnostik med jämna mellanrum för att säkerställa att allt fungerar smidigt. Annars kan du felsöka och lösa eventuella problem som du identifierar.

Nästa steg

Om du vill hitta peer-svar på dina viktigaste frågor eller för att publicera eller besvara en fråga går du till Stack Overflow.