MySQL gibt keinen Speicher frei

8

MySQL scheint eine ganze Tabelle im Cache behalten zu wollen (Tabellengröße = ~ 20 GB), nachdem große Einfügungen oder Select-Anweisungen ausgeführt wurden. Im Moment ist mein Innodb-Pufferpool 20 GB groß. Der Gesamtspeicher beträgt 32 GB. Ich werde einige Speichernutzung und Ausgabe vom Innodb-Status sowie Ausgabe von mysqltuner bereitstellen. Es hat mich in den letzten Tagen verrückt gemacht. Bitte helfen Sie! Ich freue mich über Feedback und bitte lassen Sie mich wissen, wenn Sie weitere Informationen benötigen.

Wenn Sie eine 'FLUSH TABLES' ausführen, werden diese nur geschlossen und im Speicher wieder geöffnet. Zumindest denke ich, dass das passiert. Hier ist der aktuelle Speicherstatus von innodb, bevor ich eine Reihe von Einfügungen durchgeführt habe:

----------------------
BUFFER POOL AND MEMORY
----------------------
Total memory allocated 21978152960; in additional pool allocated 0
Dictionary memory allocated 6006471
Buffer pool size   1310719
Free buffers       347984
Database pages     936740
Old database pages 345808
Modified db pages  0
Pending reads 0
Pending writes: LRU 0, flush list 0, single page 0
Pages made young 78031, not young 0
0.00 youngs/s, 0.00 non-youngs/s
Pages read 551887, created 384853, written 4733512
0.00 reads/s, 0.00 creates/s, 0.00 writes/s
No buffer pool page gets since the last printout
Pages read ahead 0.00/s, evicted without access 0.00/s, Random read ahead 0.00/s
LRU len: 936740, unzip_LRU len: 0
I/O sum[0]:cur[0], unzip sum[0]:cur[0]

mysqld Prozent Speicherauslastung: 60,9%

mysqld Prozent Speicherauslastung nach Einfügungen (1 Mil Datensätze): 63,3%

und dann nach weiteren Beilagen (3 mil Datensätze): 70,2%

Sollte es nicht bei 62,5% liegen ? (20 / 32GB) RAM insgesamt?

Ausgabe von oben Sortieren meiner MEM-Nutzung:

top - 14:30:56 up 23:25,  3 users,  load average: 3.63, 2.31, 1.91
Tasks: 208 total,   4 running, 204 sleeping,   0 stopped,   0 zombie
Cpu(s): 96.0%us,  3.0%sy,  0.0%ni,  0.0%id,  1.0%wa,  0.0%hi,  0.0%si,  0.0%st
Mem:  28821396k total, 28609868k used,   211528k free,   138696k buffers
Swap: 33554428k total,    30256k used, 33524172k free,  1208184k cached

  PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND
 1228 mysql     20   0 25.1g  19g 5512 S   31 70.2  62:01.10 mysqld

Hier ist die Innodb-Speicherausgabe, nachdem diese Einfügungen ausgeführt wurden:

----------------------
BUFFER POOL AND MEMORY
----------------------
Total memory allocated 21978152960; in additional pool allocated 0
Dictionary memory allocated 6006471
Buffer pool size   1310719
Free buffers       271419
Database pages     1011886
Old database pages 373510
Modified db pages  4262
Pending reads 1
Pending writes: LRU 0, flush list 0, single page 0
Pages made young 82521, not young 0
7.08 youngs/s, 0.00 non-youngs/s
Pages read 585218, created 426667, written 5192189
24.08 reads/s, 53.08 creates/s, 1135.07 writes/s
Buffer pool hit rate 1000 / 1000, young-making rate 0 / 1000 not 0 / 1000
Pages read ahead 0.00/s, evicted without access 0.00/s, Random read ahead 0.00/s
LRU len: 1011886, unzip_LRU len: 0
I/O sum[0]:cur[266], unzip sum[0]:cur[0]

Entsprechend dem Innodb-Status ist der zugewiesene Gesamtspeicher derselbe. Mein Betriebssystem (Virtual Ubuntu Server 12.04) meldet jedoch mehr Speichernutzung. Die Speichernutzung bleibt gleich und hier definiere ich sie als den MySQL-Dienst, der keinen Speicher "freigibt". Irgendwelche Vorschläge?

Ausgabe von mysqltuner.pl:

-------- Storage Engine Statistics -------------------------------------------
[--] Status: +ARCHIVE +BLACKHOLE +CSV -FEDERATED +InnoDB +MRG_MYISAM
[--] Data in MyISAM tables: 226M (Tables: 287)
[--] Data in InnoDB tables: 33G (Tables: 1000)
[--] Data in PERFORMANCE_SCHEMA tables: 0B (Tables: 17)
[--] Data in MEMORY tables: 0B (Tables: 1)
[!!] Total fragmented tables: 959

-------- Security Recommendations  -------------------------------------------
[OK] All database users have passwords assigned

-------- Performance Metrics -------------------------------------------------
[--] Up for: 23h 14m 27s (1M q [14.603 qps], 6K conn, TX: 16B, RX: 1B)
[--] Reads / Writes: 46% / 54%
[--] Total buffers: 22.2G global + 2.7M per thread (151 max threads)
[OK] Maximum possible memory usage: 22.6G (82% of installed RAM)
[OK] Slow queries: 0% (6/1M)
[OK] Highest usage of available connections: 6% (10/151)
[OK] Key buffer size / total MyISAM indexes: 2.0G/58.7M
[OK] Key buffer hit rate: 100.0% (216M cached / 38K reads)
[OK] Query cache efficiency: 81.2% (799K cached / 984K selects)
[!!] Query cache prunes per day: 5561
[OK] Sorts requiring temporary tables: 4% (819 temp sorts / 16K sorts)
[!!] Temporary tables created on disk: 27% (6K on disk / 22K total)
[OK] Thread cache hit rate: 99% (11 created / 6K connections)
[!!] Table cache hit rate: 0% (97 open / 10K opened)
[OK] Open file limit used: 12% (129/1K)
[OK] Table locks acquired immediately: 99% (433K immediate / 433K locks)
[!!] InnoDB  buffer pool / data size: 20.0G/33.6G
[OK] InnoDB log waits: 0
-------- Recommendations -----------------------------------------------------
General recommendations:
    Run OPTIMIZE TABLE to defragment tables for better performance
    MySQL started within last 24 hours - recommendations may be inaccurate
    Enable the slow query log to troubleshoot bad queries
    When making adjustments, make tmp_table_size/max_heap_table_size equal
    Reduce your SELECT DISTINCT queries without LIMIT clauses
    Increase table_cache gradually to avoid file descriptor limits
    Read this before increasing table_cache over 64: http://bit.ly/1mi7c4C
Variables to adjust:
    query_cache_size (> 128M)
    tmp_table_size (> 128M)
    max_heap_table_size (> 16M)
    table_cache (> 431)
    innodb_buffer_pool_size (>= 33G)
cherner
quelle

Antworten:

8

Schauen Sie sich zunächst die InnoDB-Architektur an (mit freundlicher Genehmigung von Percona CTP Vadim Tkachenko).

InnoDB-Architektur

InnoDB

Ihr Status für den Pufferpool lautet

Pufferpoolgröße 1310719

Das ist Ihre Puffergröße in Seiten. Jede Seite ist 16 KB groß . Das ergibt 20G - 16K.

Beachten Sie Folgendes: Sie haben Daten in den InnoDB-Pufferpool verschoben. Was hat sich geändert ?

Buffer pool size   1310719 
Free buffers       271419 (It was 347984)
Database pages     1011886 (Is was 936740)
Old database pages 373510 (It was 345808)
Modified db pages  4262 (It was 0)

Beachten Sie auch den Unterschied zwischen der Pufferpoolgröße in Seiten.

1310719 (Pufferpoolgröße) - 1011886 (Datenbankseiten) = 298833

Das sind 298833 InnoDB-Seiten. Wie viel Platz ist das ???

mysql> select FORMAT(((1310719  - 1011886) * 16384) / power(1024,3),3) SpaceUsed;
+-----------+
| SpaceUsed |
+-----------+
| 4.560     |
+-----------+

Das sind 4,56 GB. Dieser Speicherplatz wird für den Abschnitt "Puffer einfügen" des InnoDB-Pufferpools (auch als "Puffer ändern" bezeichnet) verwendet . Dies wird verwendet, um Änderungen an nicht eindeutigen Indizes in der System-Tablespace-Datei (die alle als bekannt geworden sind ibdata1) zu verringern .

Die InnoDB Storage Engine verwaltet die Interna des Pufferpools. Daher wird InnoDB niemals 62,5% des Arbeitsspeichers überschreiten. Darüber hinaus wird der RAM für den Pufferpool niemals zurückgegeben.

Woher kommen die 70,2% des RAM?

Schauen Sie sich die Ausgabe mysqltuner.pldieser Zeilen noch einmal an

[OK] Maximum possible memory usage: 22.6G (82% of installed RAM)
Key buffer size / total MyISAM indexes: 2.0G/58.7M
[--] Total buffers: 22.2G global + 2.7M per thread (151 max threads)

mysqld bietet drei Hauptmethoden für die Zuweisung von RAM

Jeder kleine Anstieg in DB Connections erhöht den Arbeitsspeicher über den für InnoDB angezeigten Schwellenwert von 62,5%.

MyISAM (Randnotiz)

Was mir auffällt, ist

Key buffer size / total MyISAM indexes: 2.0G/58.7M

Da hast du so wenig Indizes für MyISAM. Sie können die key_buffer_size auf 64M setzen.

Sie müssen MySQL dafür nicht neu starten. Renn einfach

SET GLOBAL ket_buffer_size = 1024 * 1024 * 64;

Ändern Sie dies dann in my.cnf

[mysqld]
key_Buffer_size = 64M

Dadurch erhält das Betriebssystem 2 GB RAM. Ihre VM wird Sie einfach dafür lieben !!!

Versuche es !!!

VORBEHALT

Das Ausführen FLUSH TABLESin InnoDB-Tabellen schließt einfach Dateien gegen die .ibdDateien. Dies wird Änderungen nicht wirklich direkt vorantreiben. Die Änderungen müssen ihren Weg durch die Pipes von InnoDB finden. Deshalb sehen Sie die Spitze in Modified db pages. Die 4262 geänderten Seiten (66,59 MB) werden gelöscht, wenn InnoDBs Zeitplan das Löschen beendet.

RolandoMySQLDBA
quelle
Vielen Dank für die eingehende Analyse. Es ist jetzt viel sinnvoller - ist es also wahr, dass der Innodb-Pufferpool über die Zeit bei maximaler Speichernutzung bleibt (20 GB)? Und der Gesamtspeicher, den mysqld jemals verwenden wird, beträgt 82%?
Cherner
Das ist ein Ja zu beiden Fragen
RolandoMySQLDBA
0

Ich habe ein ähnliches Problem gehabt. Frage: Verwenden Sie die Split-Memory-Konfiguration? (THP und gemeinsam genutzt) Wenn ja, deaktivieren Sie riesige Seiten und lassen Sie The MySQL den Speicher verwalten und überwachen Sie ihn weiter. Überprüfen Sie auch, wie viele parallele Prozesse auf dem Server ausgeführt werden, einschließlich der Prozesse im Ruhemodus. Wenn Sie die Shared-Memory-Konfiguration verwenden, benötigen Sie mehr Speicher für diesen Server.

Raja Naveed
quelle