Pourquoi MySQL dit que je manque de mémoire?

9

J'essayais d'exécuter un assez grand INSERT...SELECTdans 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, je pensais que l'espace de tas Java ne devrait pas être un problème. Cependant, j'ai quand même essayé de le monter et ça n'a pas été bon. J'ai ensuite essayé d'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 à toute la table dans laquelle je sélectionne), mais je suppose qu'il y a différents paramètres que je dois modifier pour profiter de toute ma mémoire. J'exécute une instance Amazon EC2 High Memory Double Extra Large avec une AMI Windows Server 2008. J'ai essayé de jouer avec le fichier my.ini pour utiliser de meilleurs paramètres, mais pour autant que je sache, j'aurais pu aggraver les choses. Voici un vidage 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

Est-ce simplement une question de changer les paramètres ci-dessus pour mieux fonctionner 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 passe-temps 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.

Michael McGowan
la source
Quiconque utilise un cache de requêtes 1g n'a aucune idée de ce qu'il fait.
@winmutt Vous pouvez très bien avoir raison, mais votre commentaire n'aide personne sans autre explication. Pourriez-vous nous aider en donnant les raisons de votre sentiment?
Michael McGowan

Réponses:

9

É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 donne 80% de RAM installée ou moins.

sort_buffer_size
read_buffer_size
read_rnd_buffer_size
join_buffer_size
max_connections
RolandoMySQLDBA
la source
4

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 de RAM allouée (le cas échéant).

Derek Downey
la source
4

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 la RAM installée MySQL pense pouvoir allouer en toute sécurité. Si la réponse donnée est supérieure à 100%, vous devez absolument 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 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 = 128K
read_rnd_buffer_size = 256K
sort_buffer_size = 2M
join_buffer_size = 128K
max_connections = 1050

Voici la sortie de mysqltuner.pl:

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

-------- 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 prise en charge
[!!] Basculer vers un 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 tables MyISAM: 319M (Tables: 108)
[-] Données dans les tables InnoDB: 2M (Tables: 5)
[!!] Total des tableaux fragmentés: 22

-------- Indicateurs de performance ---------------------------------------- ---------
[-] Up for: 52j 23h 15m 57s (72M q [15.875 qps], 241K conn, TX: 2B, RX: 1B)
[-] Lectures / écritures: 59% / 41%
[-] Nombre total de tampons: 34,0 M global + 2,7 M par thread (1050 threads max)
[!!] L'allocation de> 2 Go de 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,0M / 82,1 M
[OK] Taux de réussite du tampon de touches: 100,0% (4B mis en cache / 1 M de lectures)
[!!] Le cache de requête est désactivé
[OK] Tris nécessitant des tables temporaires: 0% (0 tri temporaire / 948 K tri)
[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] Ouvrir le fichier limite utilisée: 2% (125 / 5K)
[OK] Verrous de table acquis immédiatement: 99% (30M verrous immédiats / 30M)
[OK] Taille des données InnoDB / pool de mémoire tampon: 2,7M / 8,0M

-------- 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 table_cache progressivement pour éviter les limites des descripteurs de fichiers
Variables pour ajuster:
query_cache_size (> = 8M)
thread_cache_size (commencer à 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% de la RAM installée en fonction des paramètres de /etc/my.cnf.

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.

RolandoMySQLDBA
la source
Je ne suis pas sûr de pouvoir utiliser votre outil; J'utilise Windows. La documentation mentionne que Windows n'est pas pris en charge, mais j'ai quand même essayé. Lorsque j'ai essayé de l'exécuter, il a indiqué qu'il ne pouvait pas trouver mysqladmin dans mon $ PATH, mais le répertoire bin de MySQL est en effet dans mon $ PATH.
Michael McGowan
Désolé, je n'ai pas remarqué le datadir de Windows. J'ajouterai une réponse différente.
RolandoMySQLDBA
1

Vous n'avez pas dit combien de 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.

Rick James
la source