web-dev-qa-db-fra.com

Comment réduire / purger le fichier ibdata1 dans MySQL

J'utilise MySQL dans localhost comme "outil de requête" pour effectuer des statistiques dans R, c'est-à-dire que chaque fois que j'exécute un script R, je crée une nouvelle base de données (A), crée une nouvelle table (B), importe les données dans B , soumettez une requête pour obtenir ce dont j'ai besoin, puis déposez B et A.

Cela fonctionne très bien pour moi, mais je me rends compte que la taille du fichier ibdata augmente rapidement, je n'ai rien stocké dans MySQL, mais le fichier ibdata1 dépassait déjà 100 Mo.

J'utilise plus ou moins les paramètres MySQL par défaut pour la configuration. Existe-t-il un moyen de réduire/purger automatiquement le fichier ibdata1 après une période déterminée?

538
lokheart

Le fait que ibdata1 ne soit pas réduit est une fonctionnalité particulièrement gênante de MySQL. Le fichier ibdata1 ne peut en réalité être réduit que si vous supprimez toutes les bases de données, supprimez les fichiers et rechargez une sauvegarde.

Mais vous pouvez configurer MySQL pour que chaque table, y compris ses index, soit stockée dans un fichier séparé. De cette façon, ibdata1 ne deviendra pas aussi gros. Selon commentaire de Bill Karwin , ceci est activé par défaut à partir de la version 5.6.6 de MySQL.

C'était il y a un moment, je l'ai fait. Cependant, pour que votre serveur utilise des fichiers séparés pour chaque table, vous devez modifier my.cnf afin de l'activer:

[mysqld]
innodb_file_per_table=1

http://dev.mysql.com/doc/refman/5.5/en/innodb-multiple-tablespaces.html

Pour récupérer l’espace de ibdata1, vous devez supprimer le fichier:

  1. Faites une mysqldump de toutes les bases de données, procédures, déclencheurs, etc. à l'exception des bases de données mysql et performance_schema
  2. Supprimer toutes les bases de données à l'exception des 2 bases de données ci-dessus
  3. Arrêtez mysql
  4. Supprimer les fichiers ibdata1 et ib_log
  5. Démarrer mysql
  6. Restaurer à partir d'un dump

Lorsque vous démarrez MySQL à l'étape 5, les fichiers ibdata1 et ib_log seront recréés.

Maintenant, vous êtes prêt à partir. Lorsque vous créez une nouvelle base de données pour analyse, les tables se trouvent dans des fichiers ibd* distincts, et non dans ibdata1. Comme vous supprimez habituellement la base de données peu de temps après, les fichiers ibd* seront supprimés.

http://dev.mysql.com/doc/refman/5.1/en/drop-database.html

Vous avez probablement vu ceci:
http://bugs.mysql.com/bug.php?id=1341

En utilisant la commande ALTER TABLE <tablename> ENGINE=innodb ou OPTIMIZE TABLE <tablename>, il est possible d'extraire les données et les pages d'index d'ibdata1 dans des fichiers séparés. Toutefois, ibdata1 ne sera pas réduit à moins de suivre les étapes ci-dessus.

En ce qui concerne le information_schema, il n’est ni nécessaire ni possible de le supprimer. En fait, il ne s'agit que d'un ensemble de vues en lecture seule, et non de tables. Et il n'y a pas de fichiers associés à eux, pas même un répertoire de base de données. Le informations_schema utilise le moteur de base de données en mémoire. Il est supprimé et régénéré à l’arrêt/au redémarrage de mysqld. Voir https://dev.mysql.com/doc/refman/5.7/en/information-schema.html .

756
John P

Ajout à réponse de John P ,

Pour un système Linux, les étapes 1 à 6 peuvent être accomplies avec les commandes suivantes:

  1. mysqldump -u [username] -p[root_password] [database_name] > dumpfilename.sql
  2. DROP DATABASE [database_name];
  3. Sudo /etc/init.d/mysqld stop
  4. Sudo rm /var/lib/mysql/ibdata1
    Sudo rm /var/lib/mysql/ib_logfile (et supprimez tout autre fichier_journal pouvant être nommé ib_logfile0, ib_logfile1 etc ...)
  5. Sudo /etc/init.d/mysqld start
  6. create database [database_name];
  7. mysql -u [username]-p[root_password] [database_name] < dumpfilename.sql

Attention: ces instructions vous feront perdre d'autres bases de données si vous en avez d'autres sur cette instance mysql. Assurez-vous que les étapes 1, 2 et 6, 7 sont modifiées pour couvrir toutes les bases de données que vous souhaitez conserver.

42
Vinay Vemula

Lorsque vous supprimez des tables innodb, MySQL ne libère pas d'espace à l'intérieur du fichier ibdata, c'est pourquoi il ne cesse de croître. Ces fichiers ne diminuent presque jamais.

Comment réduire un fichier ibdata existant:

http://dev.mysql.com/doc/refman/5.5/en/innodb-resize-system-tablespace.html

Vous pouvez créer un script et planifier l'exécution du script après une période déterminée, mais pour la configuration décrite ci-dessus, il semble que plusieurs espaces de table constituent une solution plus simple.

Si vous utilisez l'option de configuration innodb_file_per_table, vous créez plusieurs espaces de table. En d'autres termes, MySQL crée des fichiers distincts pour chaque table au lieu d'un fichier partagé. Ces fichiers séparés sont stockés dans le répertoire de la base de données et sont supprimés lorsque vous supprimez cette base de données. Cela devrait supprimer la nécessité de réduire/purger les fichiers ibdata dans votre cas.

Plus d'informations sur plusieurs espaces de table:

http://dev.mysql.com/doc/refman/5.5/en/innodb-multiple-tablespaces.html

34
titanoboa

Si vous utilisez le moteur de stockage InnoDB pour (certaines) vos tables MySQL, vous avez probablement déjà rencontré un problème avec sa configuration par défaut. Comme vous l'avez peut-être remarqué dans le répertoire de données de votre serveur MySQL (dans Debian/Ubuntu -/var/lib/mysql), vous trouverez un fichier appelé "ibdata1". Il contient presque toutes les données InnoDB (ce n’est pas un journal de transactions) de l’instance MySQL et peut devenir très volumineux. Par défaut, ce fichier a une taille initiale de 10 Mo et s’étend automatiquement. Malheureusement, par conception, les fichiers de données InnoDB ne peuvent pas être réduits. C’est pourquoi DELETE, TRUNCATE, DROP, etc. ne récupéreront pas l’espace utilisé par le fichier.

Je pense que vous pouvez trouver une bonne explication et solution ici:

http://vdachev.net/2007/02/22/mysql-reducing-ibdata1/

14
Vik

Scripté rapidement la procédure de réponse acceptée dans bash:

#!/usr/bin/env bash
DATABASES="$(mysql -e 'show databases \G' | grep "^Database" | grep -v '^Database: mysql$\|^Database: binlog$\|^Database: performance_schema\|^Database: information_schema' | sed 's/^Database: //g')"
mysqldump --databases $DATABASES -r alldatabases.sql && echo "$DATABASES" | while read -r DB; do
    mysql -e "drop database \`$DB\`"
done && \
    /etc/init.d/mysql stop && \
    find /var/lib/mysql -maxdepth 1 -type f \( -name 'ibdata1' -or -name 'ib_logfile*' \) -delete && \
    /etc/init.d/mysql start && \
    mysql < alldatabases.sql && \
    rm -f alldatabases.sql

Enregistrez sous purge_binlogs.sh et exécutez-vous sous root.

Sont exclus mysql, information_schema, performance_schema (et le répertoire binlog).

Supposons que vous avez des crédits d’administrateur dans /root/.my.cnf et que votre base de données vit dans le répertoire par défaut /var/lib/mysql.

Vous pouvez également purger les journaux binaires après avoir exécuté ce script pour regagner plus d'espace disque avec:

PURGE BINARY LOGS BEFORE CURRENT_TIMESTAMP;

Si votre objectif est de surveiller l'espace libre MySQL et que vous ne pouvez pas empêcher MySQL de réduire votre fichier ibdata, utilisez-le à l'aide des commandes de table status. Exemple:

MySQL> 5.1.24:

mysqlshow --status myInnodbDatabase myTable | awk '{print $20}'

MySQL <5.1.24:

mysqlshow --status myInnodbDatabase myTable | awk '{print $35}'

Ensuite, comparez cette valeur à votre fichier ibdata:

du -b ibdata1

Source: http://dev.mysql.com/doc/refman/5.1/en/show-table-status.html

6
Cyno

Dans une nouvelle version de mysql-server, les recettes ci-dessus écraseront la base de données "mysql". Dans l'ancienne version cela fonctionne. Dans les nouvelles tables, certaines tables basculent vers le type de table INNODB et vous risqueriez de les endommager. Le plus simple est de vider toutes vos bases de données, de désinstaller mysql-server, puis de rester dans mon.cnf:

[mysqld]
innodb_file_per_table=1


erase all in /var/lib/mysql
install mysql-server
restore users and databases
4
adjustable_wrench

Comme déjà indiqué, vous ne pouvez pas réduire ibdata1 (pour ce faire, vous devez dumper et reconstruire), mais il n’est souvent pas nécessaire de le faire.

Utilisation d’autoextend (probablement le paramètre de taille le plus courant) ibdata1 préalloue le stockage en augmentant chaque fois qu’il est presque plein. Cela accélère les écritures car l’espace est déjà alloué.

Lorsque vous supprimez des données, celles-ci ne sont pas réduites, mais l'espace à l'intérieur du fichier est marqué comme étant inutilisé. Désormais, lorsque vous insérez de nouvelles données, les espaces vides du fichier sont réutilisés avant que le fichier ne s'agrandisse davantage.

Donc, cela ne fera que continuer de croître si vous avez réellement besoin de ces données. À moins que vous n'ayez réellement besoin d'espace pour une autre application, il n'y a probablement aucune raison de la réduire.

1
steveayre