Warum sagt MySQL, dass mir der Speicher ausgeht?

9

Ich habe versucht, INSERT...SELECTmit JDBC eine ziemlich große Version in MySQL auszuführen , und habe die folgende Ausnahme erhalten:

Exception in thread "main" java.sql.SQLException: Out of memory (Needed 1073741824 bytes)
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:1073)

Da ich eigentlich kein ResultSet-Objekt zurückgebe, dachte ich, dass der Java-Heapspeicher kein Problem sein sollte. Ich habe es trotzdem versucht und es hat nicht gut getan. Ich habe dann versucht, die Anweisung in MySQL Workbench auszuführen, und habe im Wesentlichen dasselbe erhalten:

Error Code 5: Out of memory (Needed 1073741816 bytes)

Ich sollte genügend RAM haben, um diese Vorgänge abzuschließen (genug, um in die gesamte Tabelle zu passen, aus der ich auswähle), aber ich schätze, es gibt verschiedene Einstellungen, die ich anpassen muss, um meinen gesamten Speicher zu nutzen. Ich verwende eine doppelte extra große Amazon EC2- Instanz mit hohem Speicher und einem Windows Server 2008 AMI. Ich habe versucht, mit der Datei my.ini herumzuspielen, um bessere Einstellungen zu verwenden, aber soweit ich weiß, hätte ich die Dinge möglicherweise noch schlimmer gemacht. Hier ist ein Speicherauszug dieser Datei:

[client]
port=3306
[mysql]
default-character-set=latin1
[mysqld]
port=3306
basedir="C:/Program Files/MySQL/MySQL Server 5.5/"
datadir="C:/ProgramData/MySQL/MySQL Server 5.5/Data/"
character-set-server=latin1
default-storage-engine=INNODB
sql-mode="STRICT_TRANS_TABLES,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION"
max_connections=100
query_cache_size=1024M
table_cache=256
tmp_table_size=25G
thread_cache_size=8
myisam_max_sort_file_size=100G
myisam_repair_threads = 2
myisam_sort_buffer_size=10G
key_buffer_size=5000M
bulk_insert_buffer_size = 4000M
read_buffer_size=8000M
read_rnd_buffer_size=8000M
sort_buffer_size=1G
innodb_additional_mem_pool_size=26M
innodb_flush_log_at_trx_commit=2
innodb_log_buffer_size=13M
innodb_buffer_pool_size=23G
innodb_log_file_size=622M
innodb_thread_concurrency=18
innodb_file_per_table=TRUE
join_buffer_size=4G
max_heap_table_size = 10G

Geht es also nur darum, die oben genannten Einstellungen zu ändern, um für meine Umgebung besser zu funktionieren? Wenn ja, welche Einstellungen sollte ich verwenden? Ich bin der einzige, der diese Instanz jemals verwendet. Ich verwende es für mein persönliches Hobbyprojekt, bei dem große Datensätze statistisch analysiert werden. Daher kann ich zulassen, dass alle verfügbaren Ressourcen für meine eigenen Abfragen verwendet werden.

Was ist das Problem, wenn es nicht darum geht, diese Einstellungen zu ändern? Vielen Dank für jede Hilfe, die Sie anbieten können, um alles besser zu konfigurieren.

Michael McGowan
quelle
Jeder, der einen 1g-Abfragecache verwendet, hat keine Ahnung, was er tut.
@winmutt Sie mögen sehr gut richtig sein, aber Ihr Kommentar hilft niemandem ohne weitere Erklärung. Könnten Sie uns bitte helfen, indem Sie Gründe für Ihr Gefühl angeben?
Michael McGowan
Ein praktisches Tool für den Einstieg ist tools.percona.com/wizard
KCD

Antworten:

9

Da es sich um eine Windows-Installation handelt, hat @DTest immer noch die anfängliche richtige Richtung angegeben.

Wenden Sie die folgende Formel an:

Die meisten Leute benutzen dies:

Maximum MySQL Memory Usage = innodb_buffer_pool_size + key_buffer_size + (read_buffer_size + sort_buffer_size) X max_connections

Ich bevorzuge das:

Maximum MySQL Memory Usage = innodb_buffer_pool_size + key_buffer_size + ((read_buffer_size + read_rnd_buffer_size + sort_buffer_size + join_buffer_size) X max_connections)

Diese Variablen müssen angepasst werden, bis die Formel 80% des installierten RAM oder weniger ergibt.

sort_buffer_size
read_buffer_size
read_rnd_buffer_size
join_buffer_size
max_connections
RolandoMySQLDBA
quelle
4

Ich würde versuchen, Ihre Puffergrößen zu verringern. Wenn Sie sie so groß machen, wie Sie sie haben, wird dies zu Problemen führen. Wie viel Speicher steht Ihnen zur Verfügung, um diese Werte auszuführen:

query_cache_size=1024M
myisam_max_sort_file_size=100G
myisam_sort_buffer_size=10G
key_buffer_size=5000M
bulk_insert_buffer_size = 4000M
read_buffer_size=8000M
read_rnd_buffer_size=8000M
sort_buffer_size=1G
innodb_buffer_pool_size=23G

Einige der Puffergrößen werden pro Thread zugewiesen, z. B. weist myisam_sort_buffer_size von 10G jedem Thread 10G zu.

Ich würde diese Werte zuerst drastisch reduzieren und dann untersuchen, welche Werte Sie wirklich benötigen, um so viel RAM zuzuweisen (falls vorhanden).

Derek Downey
quelle
4

Ein schneller Weg, um festzustellen, wie viel Speicher MySQL zuordnen könnte, ist folgender:

wget mysqltuner.pl

perl mysqltuner.pl

Wenn Sie dieses Skript ausführen, erfahren Sie, wie viel Prozent des installierten Arbeitsspeichers MySQL seiner Meinung nach sicher zuordnen kann. Wenn die Antwort über 100% liegt, müssen Sie auf jeden Fall die Puffergröße verringern. Die wichtigsten Punkte sind:

sort_buffer_size
read_buffer_size
read_rnd_buffer_size
join_buffer_size
max_connections
key_buffer_size (nach 4G nicht wirklich effektiv)

@DTest hat bereits in seiner Antwort die Richtung für Sie festgelegt, also +1 für seine Antwort. Das Perl-Skript sagt Ihnen, was passiert, wenn Sie es nicht festlegen oder einen Wert ändern. Hier ist ein Beispiel:

Ein Client von mir hat
read_buffer_size = 128K
read_rnd_buffer_size = 256K
sort_buffer_size = 2M
join_buffer_size = 128K
max_connections = 1050

Hier ist die Ausgabe von mysqltuner.pl:

MySQLTuner 1.2.0 - Wichtige Hayden-Fehlerberichte
, Funktionsanforderungen und Downloads unter http://mysqltuner.com/
Ausführen mit '--help' für zusätzliche Optionen und Ausgabefilterung
Geben
Sie Ihren MySQL-Administrator-Login ein: lwdba Bitte geben Sie Ihren MySQL-Administrator ein Passwort:

-------- Allgemeine Statistiken ---------------------------------------- ----------
[-] Versionsprüfung für MySQLTuner-Skript übersprungen
[OK] Derzeit wird die unterstützte MySQL-Version 5.0.51a-community-log ausgeführt
[!!] Zum 64-Bit-Betriebssystem wechseln - MySQL kann derzeit nicht verwendet werden Ihr gesamtes RAM

-------- Storage Engine-Statistiken --------------------------------------- ----
[-] Status: + Archiv -BDB + Verbund + InnoDB -ISAM -NDBCluster
[-] Daten in MyISAM-Tabellen: 319M (Tabellen: 108)
[-] Daten in InnoDB-Tabellen: 2M (Tabellen: 5)
[!!] Insgesamt fragmentierte Tabellen: 22

-------- Leistungsmetriken ------------------------------------ ---------
[-] Bis zu: 52d 23h 15m 57s (72M q [15,875 qps], 241K conn, TX: 2B, RX: 1B)
[-] Lese- / Schreibvorgänge: 59% / 41%
[-] Gesamtpuffer: 34,0 Millionen global + 2,7 Millionen pro Thread (maximal 1050 Threads)
[!!] Das Zuweisen von> 2 GB RAM auf 32-Bit-Systemen kann zu Systeminstabilität führen
[!!] Maximal mögliche Speichernutzung: 2,8 G. (72% des installierten Arbeitsspeichers)
[OK] Langsame Abfragen: 0% (54 / 72M)
[OK] Höchste Auslastung der verfügbaren Verbindungen: 6% (65/1050)
[OK] Schlüsselpuffergröße / Gesamt-MyISAM-Indizes: 8,0M / 82,1M
[OK] Trefferquote des Schlüsselpuffers: 100,0% (4B zwischengespeichert / 1M gelesen)
[!!] Der Abfrage-Cache ist deaktiviert
[OK] Sortierungen, die temporäre Tabellen erfordern: 0% (0 temporäre Sortierungen / 948K-Sortierungen)
[OK] Temporäre Tabellen auf der Festplatte erstellt: 3% (11 KB auf der Festplatte / 380 KB insgesamt)
[!!] Thread-Cache ist deaktiviert
[!!] Trefferquote im Tabellen-Cache: 0% (64 offen / 32 KB geöffnet)
[OK] Datei öffnen Verwendetes Limit: 2% (125 / 5K)
[OK] Sofort erworbene Tabellensperren: 99% (
30M Sofort- / 30M Sperren) [OK] InnoDB-Datengröße / Pufferpool: 2,7M / 8,0M

-------- Empfehlungen ------------------------------------- ------------
Allgemeine Empfehlungen:
Führen Sie OPTIMIZE TABLE aus, um Tabellen für eine bessere Leistung zu defragmentieren. Aktivieren Sie
das langsame Abfrageprotokoll, um fehlerhafte Abfragen zu
beheben. Setzen Sie thread_cache_size auf 4 als Startwert.
Erhöhen Sie table_cache schrittweise, um die Einschränkungen des Dateideskriptors zu vermeiden.
Variablen zum Anpassen:
query_cache_size (> = 8M)
thread_cache_size (beginnend mit 4)
table_cache (> 64)

Bitte beachten Sie unter Leistungsmetriken

[-] Gesamtpuffer: 34,0 Millionen global + 2,7 Millionen pro Thread (maximal 1050 Threads)

dass MySQL basierend auf den Einstellungen in /etc/my.cnf bis zu 72% des installierten RAM zuweisen kann.

Der 34M basiert auf innodb_buffer_pool_size und key_buffer_size zusammen

Die 2,7 Millionen pro Thread basierten auf read_buffer_size + read_rnd_buffer_size + sort_buffer_size + join_buffer_size.

Vielfache der 2.7M basieren auf max_connections.

Daher müssen Sie diese Parameter tweeken, bis der Leistungsmetrikbericht angibt, dass Sie weniger als 100% (vorzugsweise weniger als 80%) des installierten Arbeitsspeichers haben.

RolandoMySQLDBA
quelle
Ich bin nicht sicher, ob ich Ihr Werkzeug verwenden kann. Ich benutze Windows. In der Dokumentation wurde erwähnt, dass Windows nicht unterstützt wird, aber ich habe es trotzdem versucht. Als ich versuchte, es auszuführen, zeigte es an, dass mysqladmin in meinem $ PATH nicht gefunden werden konnte, aber das bin-Verzeichnis von MySQL befindet sich tatsächlich in meinem $ PATH.
Michael McGowan
Entschuldigung, ich habe den Windows-Datenverzeichnis nicht bemerkt. Ich werde eine andere Antwort hinzufügen.
RolandoMySQLDBA
1

Sie haben nicht gesagt, wie viel RAM Sie haben? Ich gehe davon aus, dass es mindestens 32 GB sind.

innodb_buffer_pool_size - 23G

Gut für so viel RAM.

query_cache_size = 1G

Viel zu groß. Es ist ineffizient, wenn es groß ist. Empfehlen Sie nicht mehr als 50M.

key-buffer_size = 5G

Es könnte ein hartes Limit von 4G (noch) unter Windows geben, hatte ein hartes Limit von 4G. Ihr 5G hat sich möglicherweise in 1G verwandelt. Wie auch immer, wenn alle Ihre Tische InnoDB sind, warum sollten Sie den RAM verschwenden? Stellen Sie es auf 50M ein.

Da die Fehlermeldung genau 1G hatte, riecht es nach sort_buffer_size. 32M könnte vernünftig sein.

Rick James
quelle