Perché MySQL dice che ho esaurito la memoria?


9

Stavo cercando di eseguire un abbastanza grande INSERT...SELECTin MySQL con JDBC e ho ottenuto la seguente eccezione:

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

Dato che in realtà non sto restituendo un oggetto ResultSet, ho pensato che lo spazio heap Java non dovesse essere un problema. Tuttavia, ho provato a risolverlo comunque e non ha funzionato. Ho quindi cercato di eseguire la dichiarazione in MySQL Workbench e ho ottenuto sostanzialmente la stessa cosa:

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

Dovrei avere molta RAM per completare queste operazioni (abbastanza per adattarsi all'intero tavolo da cui sto selezionando), ma immagino ci siano varie impostazioni che devo modificare per sfruttare tutta la mia memoria. Sto eseguendo un'istanza extra large doppia di memoria Amazon EC2 con un AMI di Windows Server 2008. Ho provato a giocherellare con il file my.ini per utilizzare impostazioni migliori, ma per quanto ne so avrei potuto peggiorare le cose. Ecco un dump di quel file:

[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

Quindi è solo una questione di modificare le impostazioni sopra per funzionare meglio per il mio ambiente? In tal caso, quali impostazioni dovrei usare? Sono l'unico che abbia mai usato questa istanza; Lo uso per il mio progetto di hobby personale che prevede l'analisi statistica di grandi set di dati. In quanto tale, sono libero di lasciarlo consumare tutte le risorse disponibili per le mie query.

Se non si tratta di modificare tali impostazioni, qual è il problema? Grazie per l'aiuto che puoi offrire per come configurare al meglio tutto.


Chiunque utilizzi la cache di query 1g non ha idea di cosa stia facendo.

@winmutt Potresti benissimo essere corretto, ma il tuo commento non aiuta nessuno senza ulteriori spiegazioni. Potresti per favore aiutarci fornendo i motivi del tuo sentimento?
Michael McGowan,

Uno strumento utile per iniziare è tools.percona.com/wizard
KCD

Risposte:


9

Dato che si tratta di un'installazione di Windows, @DTest ha comunque fornito la direzione iniziale corretta.

Applica la seguente formula:

Molte persone usano questo:

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

Preferisco questo:

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)

Queste variabili sono quelle che devi regolare fino a quando la formula non produce l'80% della RAM installata o meno.

sort_buffer_size
read_buffer_size
read_rnd_buffer_size
join_buffer_size
max_connections

4

Vorrei provare ad abbassare le dimensioni del buffer. Renderli grandi quanto li hai causa problemi. Quanta memoria hai a disposizione per eseguire questi valori:

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

Alcune dimensioni del buffer sono allocate per thread, ad esempio myisam_sort_buffer_size di 10G alloca 10G per ogni thread.

Innanzitutto ridurrei drasticamente quei valori, e quindi analizzerei quali valori sono realmente necessari per disporre di tale quantità di RAM allocata (se presente).


4

Un modo rapido per determinare la quantità di memoria che MySQL pensa di poter allocare è il seguente:

wget mysqltuner.pl

perl mysqltuner.pl

Quando esegui questo script, ti dirà quale percentuale della RAM installata MySQL pensa di poter allocare in modo sicuro. Se la risposta fornita è superiore al 100%, è necessario ridurre le dimensioni del buffer. I principali su cui concentrarsi sono:

sort_buffer_size
read_buffer_size
read_rnd_buffer_size
join_buffer_size
max_connections
key_buffer_size (non molto efficace dopo il 4G)

@DTest ha già impostato la direzione per te nella sua risposta, quindi +1 per la sua risposta. Lo script perl ti dirà cosa succede se non lo imposti o se cambi un valore. Ecco un esempio:

Un mio cliente ha
read_buffer_size = 128K
read_rnd_buffer_size = 256K
sort_buffer_size = 2M
join_buffer_size = 128K
max_connections = 1050

Ecco l'output di mysqltuner.pl:

MySQLTuner 1.2.0 - Principali
report di bug Hayden , richieste di funzionalità e download su http://mysqltuner.com/
Esegui con '--help' per opzioni aggiuntive e filtro di output
Inserisci il tuo login amministrativo MySQL: lwdba
Inserisci il tuo amministratore MySQL parola d'ordine:

-------- Statistiche generali ---------------------------------------- ----------
[-] Controllo versione saltata per lo script MySQLTuner
[OK] Attualmente in esecuzione MySQL supportata versione 5.0.51a-community-log
[!!] Passa al sistema operativo a 64 bit - MySQL non può attualmente utilizzare tutta la tua RAM

-------- Statistiche del motore di archiviazione --------------------------------------- ----
[-] Stato: + Archivio -BDB + Federato + InnoDB -ISAM -NDBCluster
[-] Dati nelle tabelle MyISAM: 319M (Tabelle: 108)
[-] Dati nelle tabelle InnoDB: 2M (Tabelle: 5)
[!!] Totale tabelle frammentate: 22

-------- Metriche delle prestazioni ---------------------------------------- ---------
[-] Aumentato per: 52d 23h 15m 57s (72M q [15.875 qps], 241K conn, TX: 2B, RX: 1B)
[-] Letture / Scritture: 59% / 41%
[-] Buffer totali: 34,0 M globali + 2,7 M per thread (1050 max thread)
[!!] L'allocazione> 2 GB di RAM su sistemi a 32 bit può causare instabilità del sistema
[!!] Utilizzo massimo di memoria possibile: 2,8 G (72% della RAM installata)
[OK] Query lente: 0% (54 / 72M)
[OK] Utilizzo massimo delle connessioni disponibili: 6% (65/1050)
[OK] Dimensione buffer chiave / indici MyISAM totali: 8.0 M / 82,1 M
[OK] Percentuale di hit del buffer chiave: 100,0% (4B memorizzati nella cache / 1 milione di letture)
[!!] La cache delle query è disabilitata
[OK] Ordinamenti che richiedono tabelle temporanee: 0% (ordinamenti 0 temp / ordinamenti 948K)
[OK] Tabelle temporanee create su disco: 3% (11 KB su disco / 380 KB in totale)
[!!] Cache thread disabilitata
[!!] Percentuale di riscontri cache tabella: 0% (64 aperti / 32 KB aperti)
[OK] Apri file limite utilizzato: 2% (125 / 5K)
[OK] Blocchi tabella acquisiti immediatamente: 99% (blocchi 30M immediati / 30M)
[OK] Dimensione dati InnoDB / pool buffer: 2,7 M / 8,0 M

-------- Consigli ----------------------------------------- ------------
Consigli generali:
Esegui OPTIMIZE TABLE per deframmentare le tabelle per prestazioni migliori
Abilita il registro delle query lente per risolvere le query errate
Imposta thread_cache_size su 4 come valore iniziale
Aumenta gradualmente table_cache per evitare i limiti del descrittore di file
Variabili da regolare:
query_cache_size (> = 8M)
thread_cache_size (inizia da 4)
table_cache (> 64)

Si prega di notare sotto le metriche delle prestazioni

[-] Buffer totali: 34,0 M globali + 2,7 M per thread (1050 thread massimo)

che MySQL può allocare fino al 72% della RAM installata in base alle impostazioni in /etc/my.cnf.

34M si basa su innodb_buffer_pool_size e key_buffer_size combinati

Il 2.7M per thread si basava su read_buffer_size + read_rnd_buffer_size + sort_buffer_size + join_buffer_size.

I multipli di 2.7M si basano su max_connections.

Pertanto, è necessario modificare questi parametri fino a quando il rapporto sulle metriche delle prestazioni indica che hai meno del 100% (preferibilmente inferiore all'80%) di RAM installata.


Non sono sicuro di poter usare il tuo strumento; Sto usando Windows. La documentazione menzionava che Windows non è supportato, ma ci ho provato comunque. Quando ho provato a eseguirlo, ha indicato che non è stato possibile trovare mysqladmin nel mio $ PATH, ma la directory bin di MySQL è effettivamente nel mio $ PATH.
Michael McGowan,

Spiacenti, non ho notato il datadir di Windows. Aggiungerò una risposta diversa.
RolandoMySQLDBA,

1

Non hai detto quanta RAM hai? Presumo che sia almeno 32 GB.

innodb_buffer_pool_size - 23G

Buono per così tanta RAM.

query_cache_size = 1G

Troppo grande. È inefficiente quando è grande. Raccomandare non più di 50M.

key-buffer_size = 5G

Potrebbe esserci un limite rigido di 4G (ancora) su Windows, un limite rigido di 4G. Il tuo 5G potrebbe essere diventato 1G. Comunque, se tutti i tuoi tavoli sono InnoDB, perché sprecare il ram. Impostalo su 50M.

Poiché il messaggio di errore aveva esattamente 1G, ha un odore simile sort_buffer_size. 32M potrebbe essere ragionevole.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.