En af nøglefaktorerne for en effektiv MySQL-databaseserver er at have god hukommelsesallokering og -udnyttelse, især når den kører i et produktionsmiljø. Men hvordan kan du afgøre, om MySQL-udnyttelsen er optimeret? Er det rimeligt at have høj hukommelsesudnyttelse eller kræver det finjustering? Hvad hvis jeg støder på en hukommelseslækage?
Lad os dække disse emner og vise de ting, du kan tjekke i MySQL for at bestemme spor af høj hukommelsesudnyttelse.
Hukommelsesallokering i MySQL
Før vi dykker ned i den specifikke emnetitel, vil jeg lige give en kort information om, hvordan MySQL bruger hukommelse. Hukommelse spiller en betydelig ressource for hastighed og effektivitet, når du håndterer samtidige transaktioner og kører store forespørgsler. Hver tråd i MySQL kræver hukommelse, som bruges til at administrere klientforbindelser, og disse tråde deler den samme basishukommelse. Variabler som thread_stack (stack for tråde), net_buffer_length (til forbindelsesbuffer og resultatbuffer) eller med max_allowed_packet, hvor forbindelse og resultat dynamisk vil forstørre op til denne værdi, når det er nødvendigt, er variabler, der påvirker hukommelsesudnyttelsen. Når en tråd ikke længere er nødvendig, frigives den hukommelse, der er allokeret til den, og returneres til systemet, medmindre tråden går tilbage i trådcachen. I så fald forbliver hukommelsen allokeret. Forespørgselssammenføjninger, forespørgselscaches, sortering, tabelcache, tabeldefinitioner kræver hukommelse i MySQL, men disse tilskrives systemvariabler, som du kan konfigurere og indstille.
I de fleste tilfælde er de hukommelsesspecifikke variabler indstillet for en konfiguration målrettet mod en lagerbaseret specifik konfiguration såsom MyISAM eller InnoDB. Når en mysqld-instans opstår i værtssystemet, allokerer MySQL buffere og caches for at forbedre ydeevnen af databaseoperationer baseret på de indstillede værdier, der er indstillet på en specifik konfiguration. For eksempel er de mest almindelige variabler, som hver DBA indstiller i InnoDB, variablerne innodb_buffer_pool_size og innodb_buffer_pool_instances, som begge er relateret til bufferpuljehukommelsesallokering, der indeholder cachelagrede data for InnoDB-tabeller. Det er ønskeligt, hvis du har stor hukommelse og forventer at håndtere store transaktioner ved at indstille innodb_buffer_pool_instances for at forbedre samtidighed ved at opdele bufferpuljen i flere bufferpuljeforekomster.
Mens du for MyISAM skal håndtere key_buffer_size for at håndtere mængden af hukommelse, som nøglebufferen vil håndtere. MyISAM allokerer også buffer for hver samtidige tråd, som indeholder en tabelstruktur, kolonnestrukturer for hver kolonne og en buffer på størrelse 3 * N tildeles (hvor N er den maksimale rækkelængde, BLOB-kolonner ikke medregnet). MyISAM opretholder også en ekstra rækkebuffer til intern brug.
MySQL allokerer også hukommelse til midlertidige tabeller, medmindre den bliver for stor (bestemt af tmp_table_size og max_heap_table_size). Hvis du bruger MEMORY-tabeller og variabel max_heap_table_size er sat meget højt, kan dette også tage en stor hukommelse, da max_heap_table_size systemvariabel bestemmer, hvor stor en tabel kan vokse, og der er ingen konvertering til on-disk-format.
MySQL har også et Performance Schema, som er en funktion til overvågning af MySQL-aktiviteter på et lavt niveau. Når dette er aktiveret, allokerer den dynamisk hukommelse trinvist, skalerer dens hukommelsesbrug til faktisk serverbelastning, i stedet for at allokere nødvendig hukommelse under serverstart. Når hukommelsen er allokeret, frigives den ikke, før serveren genstartes.
MySQL kan også konfigureres til at allokere store hukommelsesområder til dens bufferpulje, hvis du bruger Linux, og hvis kerne er aktiveret til understøttelse af store sider, dvs. ved at bruge HugePages.
Hvad skal man tjekke, når MySQL-hukommelsen er høj
Tjek Kørende forespørgsler
Det er meget almindeligt, at MySQL DBA'er først berører, hvad der foregår med den kørende MySQL-server. De mest grundlæggende procedurer er tjek procesliste, tjek serverstatus og tjek lagermotorstatus. For at gøre disse ting skal du dybest set bare køre rækken af forespørgsler ved at logge ind på MySQL. Se nedenfor:
For at se de kørende forespørgsler,
mysql> SHOW [FULL] PROCESSLIST;
Visning af den aktuelle procesliste afslører forespørgsler, der kører aktivt eller endda inaktive eller sovende processer. Det er meget vigtigt og er en væsentlig rutine at have en registrering af forespørgsler, der kører. Som nævnt om, hvordan MySQL allokerer hukommelse, vil kørende forespørgsler bruge hukommelsesallokering og kan drastisk forårsage ydeevneproblemer, hvis de ikke overvåges.
Se MySQL-serverens statusvariabler,
mysql> SHOW SERVER STATUS\G
eller filtrer specifikke variabler som
mysql> SHOW SERVER STATUS WHERE variable_name IN ('<var1>', 'var2'...);
MySQL's statusvariable tjener som din statistiske information til at fange metriske data for at bestemme, hvordan din MySQL klarer sig ved at observere tællerne givet af statusværdierne. Der er visse værdier her, som giver dig et blik, der påvirker hukommelsesudnyttelsen. For eksempel kontrol af antallet af tråde, antallet af tabelcaches eller bufferpuljens brug,
...
| Created_tmp_disk_tables | 24240 |
| Created_tmp_tables | 334999 |
…
| Innodb_buffer_pool_pages_data | 754 |
| Innodb_buffer_pool_bytes_data | 12353536 |
...
| Innodb_buffer_pool_pages_dirty | 6 |
| Innodb_buffer_pool_bytes_dirty | 98304 |
| Innodb_buffer_pool_pages_flushed | 30383 |
| Innodb_buffer_pool_pages_free | 130289 |
…
| Open_table_definitions | 540 |
| Open_tables | 1024 |
| Opened_table_definitions | 540 |
| Opened_tables | 700887 |
...
| Threads_connected | 5 |
...
| Threads_cached | 2 |
| Threads_connected | 5 |
| Threads_created | 7 |
| Threads_running | 1 |
Se motorens skærmstatus, for eksempel InnoDB-status
mysql> SHOW ENGINE INNODB STATUS\G
InnoDB-status afslører også den aktuelle status for transaktioner, som storage-motoren behandler. Det giver dig heap-størrelsen af en transaktion, adaptive hash-indekser, der afslører dens bufferbrug, eller viser dig indodb bufferpuljen information ligesom eksemplet nedenfor:
---TRANSACTION 10798819, ACTIVE 0 sec inserting, thread declared inside InnoDB 1201
mysql tables in use 1, locked 1
1 lock struct(s), heap size 1136, 0 row lock(s), undo log entries 8801
MySQL thread id 68481, OS thread handle 139953970235136, query id 681821 localhost root copy to tmp table
ALTER TABLE NewAddressCode2_2 ENGINE=INNODB
…
-------------------------------------
INSERT BUFFER AND ADAPTIVE HASH INDEX
-------------------------------------
Ibuf: size 528, free list len 43894, seg size 44423, 1773 merges
merged operations:
insert 63140, delete mark 0, delete 0
discarded operations:
insert 0, delete mark 0, delete 0
Hash table size 553193, node heap has 1 buffer(s)
Hash table size 553193, node heap has 637 buffer(s)
Hash table size 553193, node heap has 772 buffer(s)
Hash table size 553193, node heap has 1239 buffer(s)
Hash table size 553193, node heap has 2 buffer(s)
Hash table size 553193, node heap has 0 buffer(s)
Hash table size 553193, node heap has 1 buffer(s)
Hash table size 553193, node heap has 1 buffer(s)
115320.41 hash searches/s, 10292.51 non-hash searches/s
...
----------------------
BUFFER POOL AND MEMORY
----------------------
Total large memory allocated 2235564032
Dictionary memory allocated 3227698
Internal hash tables (constant factor + variable factor)
Adaptive hash index 78904768 (35404352 + 43500416)
Page hash 277384 (buffer pool 0 only)
Dictionary cache 12078786 (8851088 + 3227698)
File system 1091824 (812272 + 279552)
Lock system 5322504 (5313416 + 9088)
Recovery system 0 (0 + 0)
Buffer pool size 131056
Buffer pool size, bytes 2147221504
Free buffers 8303
Database pages 120100
Old database pages 44172
Modified db pages 108784
Pending reads 0
Pending writes: LRU 2, flush list 342, single page 0
Pages made young 533709, not young 181962
3823.06 youngs/s, 1706.01 non-youngs/s
Pages read 4104, created 236572, written 441223
38.09 reads/s, 339.46 creates/s, 1805.87 writes/s
Buffer pool hit rate 1000 / 1000, young-making rate 12 / 1000 not 5 / 1000
Pages read ahead 0.00/s, evicted without access 0.00/s, Random read ahead 0.00/s
LRU len: 120100, unzip_LRU len: 0
I/O sum[754560]:cur[8096], unzip sum[0]:cur[0]
…
En anden ting at tilføje, du kan også bruge Performance Schema og sys-skema til at overvåge hukommelsesforbrug og -brug af din MySQL-server. Som standard er de fleste instrumenter deaktiveret som standard, så der er manuelle ting at gøre for at bruge dette.
Se efter ombytning
I hvert fald er det sandsynligt, at MySQL udskifter sin hukommelse til disk. Dette er ofte en meget almindelig situation, især når MySQL-serveren og den underliggende hardware ikke er indstillet optimalt parallelt med de forventede krav. Der er visse tilfælde, hvor efterspørgslen efter trafik ikke er blevet forudset, hukommelsen kan vokse mere og mere, især hvis der køres dårlige forespørgsler, der forårsager at forbruge eller udnytte en masse hukommelsesplads, hvilket forårsager forringet ydeevne, da data plukkes på disken i stedet for på bufferen. For at tjekke for swappiness skal du bare køre freemem-kommandoen eller vmstat ligesom nedenfor,
[[email protected] ~]# free -m
total used free shared buff/cache available
Mem: 3790 2754 121 202 915 584
Swap: 1535 39 1496
[[email protected] ~]# vmstat 5 5
procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
r b swpd free buff cache si so bi bo in cs us sy id wa st
2 0 40232 124100 0 937072 2 3 194 1029 477 313 7 2 91 1 0
0 0 40232 123912 0 937228 0 0 0 49 1247 704 13 3 84 0 0
1 0 40232 124184 0 937212 0 0 0 35 751 478 6 1 93 0 0
0 0 40232 123688 0 937228 0 0 0 15 736 487 5 1 94 0 0
0 0 40232 123912 0 937220 0 0 3 74 1065 729 8 2 89 0 0
Du kan også tjekke ved hjælp af procfs og indsamle oplysninger, såsom at gå til /proc/vmstat eller /proc/meminfo.
Brug af Perf, gdb og Valgrind med Massif
Brug af værktøjer som perf, gdb og valgrind hjælper dig med at grave ind i en mere avanceret metode til at bestemme MySQL-hukommelsesudnyttelse. Der er tidspunkter, hvor et interessant resultat bliver et mysterium med at løse hukommelsesforbrug, der fører til din forvirring i MySQL. Dette viser behovet for at have mere skepsis, og brugen af disse værktøjer hjælper dig med at undersøge, hvordan MySQL bruger håndteringshukommelse fra tildeling af den til at bruge den til behandling af transaktioner eller processer. Dette er f.eks. nyttigt, hvis du observerer, at MySQL opfører sig unormalt, hvilket kan forårsage dårlig konfiguration eller kunne føre til fund af hukommelseslækager.
For eksempel afslører brug af perf i MySQL flere oplysninger i en rapport på systemniveau:
[[email protected] ~]# perf report --input perf.data --stdio
# To display the perf.data header info, please use --header/--header-only options.
#
#
# Total Lost Samples: 0
#
# Samples: 54K of event 'cpu-clock'
# Event count (approx.): 13702000000
#
# Overhead Command Shared Object Symbol
# ........ ....... ................... ...................................................................................................................................................................................................
#
60.66% mysqld [kernel.kallsyms] [k] _raw_spin_unlock_irqrestore
2.79% mysqld libc-2.17.so [.] __memcpy_ssse3
2.54% mysqld mysqld [.] ha_key_cmp
1.89% mysqld [vdso] [.] __vdso_clock_gettime
1.05% mysqld mysqld [.] rec_get_offsets_func
1.03% mysqld mysqld [.] row_sel_field_store_in_mysql_format_func
0.92% mysqld mysqld [.] _mi_rec_pack
0.91% mysqld [kernel.kallsyms] [k] finish_task_switch
0.90% mysqld mysqld [.] row_search_mvcc
0.86% mysqld mysqld [.] decimal2bin
0.83% mysqld mysqld [.] _mi_rec_check
….
Da dette kan være et særligt emne at grave i, foreslår vi, at du kigger på disse virkelig gode eksterne blogs som dine referencer, perf Basics for MySQL Profiling, Finding MySQL-scaling problemer ved at bruge perf, eller lærer at debug ved hjælp af valgrind med massiv.
Effektiv måde at kontrollere MySQL-hukommelsesudnyttelse på
Brug af ClusterControl letter alle besværlige rutiner som at gennemgå dine runbooks eller endda oprette dine egne playbooks, der kunne levere rapporter til dig. I ClusterControl har du Dashboards (ved hjælp af SCUMM), hvor du kan få et hurtigt overblik over dine MySQL-noder. For eksempel ved at se MySQL General-dashboardet,
du kan bestemme, hvordan MySQL-noden fungerer,
Du kan se, at billederne ovenfor afslører variabler, der påvirker MySQL-hukommelsesudnyttelsen. Du kan kontrollere, hvordan metrikken for sortering af caches, midlertidige tabeller, tråde forbundet, forespørgselscache eller lagermotorer innodb bufferpool eller MyISAM's nøglebuffer.
Brug af ClusterControl giver dig et one-stop-værktøj, hvor du også kan kontrollere forespørgsler, der kører for at bestemme de processer (forespørgsler), der kan påvirke høj hukommelsesudnyttelse. Se nedenfor for et eksempel,
Det er nemt at se statusvariablerne for MySQL,
Du kan endda gå til Ydeevne -> Innodb-status for at afsløre aktuelle InnoDB-status for dine databasenoder. I ClusterControl opdages der også en hændelse, den vil forsøge at indsamle hændelse og viser historik som en rapport, der giver dig InnoDB-status som vist i vores tidligere blog om MySQL Freeze Frame.
Oversigt
Fejlfinding og diagnosticering af din MySQL-database ved mistanke om høj hukommelsesudnyttelse er ikke så svært, så længe du kender de procedurer og værktøjer, du skal bruge. Brug af det rigtige værktøj giver dig mere fleksibilitet og hurtigere produktivitet til at levere rettelser eller løsninger med en chance for større resultat.