web-dev-qa-db-fra.com

Pourquoi MySQL dit que je manque de mémoire?

J'essayais d'exécuter un assez gros INSERT...SELECT dans MySQL avec JDBC, et j'ai eu l'exception suivante:

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

Comme je ne retourne pas réellement un objet ResultSet, j'ai pensé que l'espace de tas Java ne devrait pas être un problème. Cependant, j'ai quand même essayé de le monter et cela n'a pas été bon. J'ai ensuite essayé pour exécuter l'instruction dans MySQL Workbench et j'ai essentiellement obtenu la même chose:

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

Je devrais avoir beaucoup de RAM pour terminer ces opérations (suffisamment pour s'adapter à l'ensemble du tableau dans lequel je sélectionne), mais je suppose qu'il existe divers paramètres dont j'ai besoin de Tweak pour tirer parti de toute ma mémoire. J'utilise un Amazon EC2 High Memory Double Extra Large Instance avec une AMI Windows Server 2008. J'ai essayé de jouer avec le fichier my.ini pour utiliser de meilleurs paramètres, mais pour tous Je sais que j'aurais pu aggraver les choses. Voici un cliché de ce fichier:

[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

Alors, s'agit-il simplement de modifier les paramètres ci-dessus pour qu'ils fonctionnent mieux dans mon environnement? Si oui, quels paramètres dois-je utiliser? Je suis le seul à avoir utilisé cette instance; Je l'utilise pour mon projet de loisir personnel qui implique l'analyse statistique de grands ensembles de données. En tant que tel, je suis libre de le laisser consommer toutes les ressources disponibles pour mes propres requêtes.

S'il ne s'agit pas de modifier ces paramètres, quel est le problème? Merci pour toute aide que vous pouvez offrir pour mieux configurer tout.

9
Michael McGowan

Étant donné qu'il s'agit d'une installation Windows, @DTest a toujours fourni la bonne direction initiale.

Appliquez la formule suivante:

La plupart des gens utilisent ceci:

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

Je préfère ça:

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)

Ces variables sont celles que vous devez ajuster jusqu'à ce que la formule produise 80% de RAM ou moins) installé.

sort_buffer_size
read_buffer_size
read_rnd_buffer_size
join_buffer_size
max_connections
9
RolandoMySQLDBA

J'essaierais de réduire la taille de vos tampons. Les rendre aussi grands que vous les aurez va causer des problèmes. De combien de mémoire disposez-vous pour exécuter ces valeurs:

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

Certaines tailles de mémoire tampon sont allouées par thread, par exemple myisam_sort_buffer_size de 10G alloue 10G pour chaque thread.

Je voudrais d'abord réduire ces valeurs de façon spectaculaire, puis rechercher les valeurs dont vous avez vraiment besoin pour avoir autant RAM allouée (le cas échéant).

4
Derek Downey

Un moyen rapide de déterminer la quantité de mémoire que MySQL pense pouvoir allouer est la suivante:

wget mysqltuner.pl

Perl mysqltuner.pl

Lorsque vous exécutez ce script, il vous indiquera quel pourcentage de RAM MySQL pense qu'il peut allouer en toute sécurité. Si la réponse donnée est supérieure à 100%, vous devez certainement réduire la taille de votre tampon. Les principaux points sur lesquels se concentrer sont:

sort_buffer_size
read_buffer_size
read_rnd_buffer_size
join_buffer_size
max_connections
key_buffer_size (pas vraiment efficace après la 4G)

@DTest a déjà défini la direction pour vous dans sa réponse, donc +1 pour sa réponse. Le script Perl vous dira ce qui se passe si vous ne le définissez pas ou si vous modifiez une valeur. Voici un exemple:

Un de mes clients a
read_buffer_size = 128 Ko
read_rnd_buffer_size = 256 Ko
sort_buffer_size = 2M
join_buffer_size = 128 Ko
max_connections = 1050

Voici la sortie de mysqltuner.pl:

MySQLTuner 1.2.0 - Major Hayden
Rapports de bogues, demandes de fonctionnalités et téléchargements sur http://mysqltuner.com/
Exécutez avec '--help' pour des options supplémentaires et le filtrage de sortie
Veuillez saisir votre identifiant administratif MySQL: lwdba
Veuillez saisir votre mot de passe administrateur MySQL:

-------- Statistiques générales ---------------------------------------- ----------
[-] Vérification de version ignorée pour le script MySQLTuner
[OK] Actuellement en cours d'exécution MySQL version 5.0.51a-community-log pris en charge
[!!] Passer au système d'exploitation 64 bits - MySQL ne peut pas actuellement utiliser toute votre RAM

-------- Statistiques du moteur de stockage --------------------------------------- ----
[-] Statut: + Archive -BDB + Federated + InnoDB -ISAM -NDBCluster
[-] Données dans les tableaux MyISAM: 319 M (tableaux: 108)
[-] Données dans les tableaux InnoDB: 2M (tableaux: 5)
[!!] Total des tableaux fragmentés: 22

-------- Indicateurs de performance ---------------------------------------- ---------
[-] Disponible pour: 52j 23h 15m 57s (72M q [15.875 qps], 241K conn, TX: 2B, RX: 1B)
[-] Lit/écrit: 59%/41%
[-] Nombre total de tampons: 34,0 M global + 2,7 M par thread (1050 threads max)
[!!] L'allocation> 2 Go RAM sur les systèmes 32 bits peut provoquer une instabilité du système
[!!] Utilisation maximale possible de la mémoire: 2,8 G (72% de la RAM installée)
[OK] Requêtes lentes: 0% (54/72M)
[OK] Utilisation la plus élevée des connexions disponibles: 6% (65/1050)
[OK] Taille de la mémoire tampon/total des index MyISAM: 8,0 M/82,1 M
[OK] Taux de réussite du tampon de touches: 100,0% (4B en cache/1M de lectures)
[!!] Le cache de requête est désactivé
[OK] Tris nécessitant des tables temporaires: 0% (0 tri temporaire/tri 948 Ko)
[OK] Tables temporaires créées sur le disque: 3% (11 Ko sur le disque/380 Ko au total)
[!!] Le cache de threads est désactivé
[!!] Taux de réussite du cache de table: 0% (64 ouvert/32 Ko ouvert)
[OK] Limite d'ouverture de fichiers utilisée: 2% (125/5K)
[OK] Verrous de table acquis immédiatement: 99% (30M verrous immédiats/30M verrous)
[OK] Taille des données/pool de mémoire tampon InnoDB: 2,7 M/8,0 M

-------- Recommandations ----------------------------------------- ------------
Recommandations générales:
Exécutez OPTIMIZE TABLE pour défragmenter les tables pour de meilleures performances
Activez le journal des requêtes lentes pour résoudre les mauvaises requêtes
Définissez thread_cache_size sur 4 comme valeur de départ
Augmentez progressivement table_cache pour éviter les limites des descripteurs de fichiers
Variables à ajuster:
query_cache_size (> = 8M)
thread_cache_size (à partir de 4)
table_cache (> 64)

Veuillez noter sous les mesures de performance

[-] Nombre total de tampons: 34,0 M global + 2,7 M par thread (1050 threads max)

que MySQL peut allouer jusqu'à 72% du RAM basé sur les paramètres de /etc/my.cnf installé).

Le 34M est basé sur innodb_buffer_pool_size et key_buffer_size combinés

Les 2,7 millions par thread étaient basés sur read_buffer_size + read_rnd_buffer_size + sort_buffer_size + join_buffer_size.

Les multiples du 2.7M sont basés sur max_connections.

Par conséquent, vous devez modifier ces paramètres jusqu'à ce que le rapport de mesure des performances indique que vous avez moins de 100% (de préférence moins de 80%) de RAM installée.

4
RolandoMySQLDBA

Vous n'avez pas dit combien RAM vous avez? Je suppose que c'est au moins 32 Go.

innodb_buffer_pool_size - 23G

Bon pour autant de RAM.

query_cache_size = 1G

Beaucoup trop gros. Il est inefficace quand il est gros. Recommander pas plus de 50M.

key-buffer_size = 5G

Il pourrait y avoir une limite fixe de 4G (toujours) sur Windows, avec une limite fixe de 4G. Votre 5G est peut-être devenu 1G. Quoi qu'il en soit, si toutes vos tables sont InnoDB, pourquoi gaspiller le bélier. Réglez-le à 50M.

Étant donné que le message d'erreur avait exactement 1G, il sent comme sort_buffer_size. 32M pourrait être raisonnable.

1
Rick James