web-dev-qa-db-fra.com

Comment: nettoyer un moteur de stockage mysql InnoDB?

Est-il possible de nettoyer un moteur de stockage mysql innodb afin qu'il ne stocke pas de données à partir de tables supprimées?

Ou dois-je reconstruire une nouvelle base de données à chaque fois?

128
Bryan Field

Voici une réponse plus complète en ce qui concerne InnoDB. C'est un peu long, mais ça en vaut la peine.

N'oubliez pas que _/var/lib/mysql/ibdata1_ est le fichier le plus occupé de l'infrastructure InnoDB. Il contient normalement six types d’informations:

  • Données de table
  • Index de table
  • MVCC (contrôle de simultanéité multiversioning) Données
    • Segments de restauration
    • Annuler l'espace
  • Métadonnées de table (dictionnaire de données)
  • Double Write Buffer (écriture en arrière-plan pour éviter de dépendre de la mise en cache du système d'exploitation)
  • Insert Buffer (gestion des modifications apportées aux index secondaires non uniques)
  • Voir le Pictorial Representation of ibdata1

Architecture InnoDB

InnoDB Architecture

De nombreuses personnes créent plusieurs fichiers ibdata dans l'espoir d'améliorer la gestion de l'espace disque et les performances, mais cette conviction est erronée.

Puis-je exécuter OPTIMIZE TABLE ?

Malheureusement, vous exécutez OPTIMIZE TABLE sur une table InnoDB stockée dans le fichier d'espace table partagé _ibdata1_ fait deux choses:

  • Rend les données et les index de la table contigus dans _ibdata1_
  • Augmente _ibdata1_ parce que les données contiguës et les pages d'index sont ajoutées à _ibdata1_

Vous pouvez toutefois séparer les données de table et les index de table de _ibdata1_ et les gérer indépendamment.

Puis-je exécuter OPTIMIZE TABLE avec innodb_file_per_table ?

Supposons que vous ajoutiez innodb_file_per_table à /etc/my.cnf (my.ini). Pouvez-vous alors simplement lancer OPTIMIZE TABLE sur toutes les tables InnoDB?

Bonne nouvelle : lorsque vous exécutez OPTIMIZE TABLE avec innodb_file_per_table activé, cela produira un fichier _.ibd_ pour cette table. . Par exemple, si vous avez la table _mydb.mytable_ avec un datadir de _/var/lib/mysql_, elle produira les éléments suivants:

  • _/var/lib/mysql/mydb/mytable.frm_
  • _/var/lib/mysql/mydb/mytable.ibd_

_.ibd_ contiendra les pages de données et les pages d'index pour cette table. Génial.

Mauvaise nouvelle : Tout ce que vous avez fait est d'extraire les pages de données et les pages d'index de _mydb.mytable_ de la vie en ibdata. L'entrée du dictionnaire de données pour chaque table, y compris _mydb.mytable_, reste dans le dictionnaire de données (voir le représentation illustrée de ibdata1 ). VOUS NE POUVEZ PAS SUPPRIMER SIMPLEMENT _ibdata1_ AT CE POINT !!! Veuillez noter que _ibdata1_ n'a pas du tout diminué.

Nettoyage des infrastructures InnoDB

Pour réduire _ibdata1_ une fois pour toutes, vous devez procéder comme suit:

  1. Sauvegardez (par exemple, avec mysqldump) toutes les bases de données dans un fichier texte _.sql_ (_SQLData.sql_ est utilisé ci-dessous)

  2. Supprimez toutes les bases de données (sauf mysql et _information_schema_) MISE EN GARDE: Par précaution, exécutez ce script pour créer absolument sûr que vous avez toutes les subventions utilisateur en place:

    _mkdir /var/lib/mysql_grants
    cp /var/lib/mysql/mysql/* /var/lib/mysql_grants/.
    chown -R mysql:mysql /var/lib/mysql_grants
    _
  3. Connectez-vous à mysql et exécutez _SET GLOBAL innodb_fast_shutdown = 0;_ (Ceci effacera complètement toutes les modifications transactionnelles restantes de _ib_logfile0_ et _ib_logfile1_)

  4. Arrêter MySQL

  5. Ajoutez les lignes suivantes à _/etc/my.cnf_ (ou _my.ini_ sous Windows)

    _[mysqld]
    innodb_file_per_table
    innodb_flush_method=O_DIRECT
    innodb_log_file_size=1G
    innodb_buffer_pool_size=4G
    _

    (Note: Quel que soit votre choix pour _innodb_buffer_pool_size_, assurez-vous que _innodb_log_file_size_ correspond à 25% de _innodb_buffer_pool_size_.

    Aussi: _innodb_flush_method=O_DIRECT_ n'est pas disponible sous Windows)

  6. Supprimer _ibdata*_ et _ib_logfile*_, Vous pouvez éventuellement supprimer tous les dossiers de _/var/lib/mysql_, à l'exception de _/var/lib/mysql/mysql_.

  7. Démarrez MySQL (Ceci recréera _ibdata1_ [10 Mo par défaut] et _ib_logfile0_ et _ib_logfile1_ à 1G chacun).

  8. Importer _SQLData.sql_

Maintenant, _ibdata1_ continuera à croître mais ne contiendra que des métadonnées de table car chaque table InnoDB existera en dehors de _ibdata1_. _ibdata1_ ne contiendra plus de données InnoDB ni d'index pour d'autres tables.

Par exemple, supposons que vous ayez une table InnoDB nommée _mydb.mytable_. Si vous regardez dans _/var/lib/mysql/mydb_, vous verrez deux fichiers représentant la table:

  • _mytable.frm_ (en-tête du moteur de stockage)
  • _mytable.ibd_ (données de table et index)

Avec l'option _innodb_file_per_table_ dans _/etc/my.cnf_, vous pouvez exécuter _OPTIMIZE TABLE mydb.mytable_ et le fichier _/var/lib/mysql/mydb/mytable.ibd_ sera en fait réduit.

C'est ce que j'ai souvent fait dans ma carrière de DBA MySQL. En fait, la première fois que j'ai fait cela, j'ai réduit un fichier 50 Go _ibdata1_ à seulement 500 Mo!

Essaie. Si vous avez d'autres questions à ce sujet, il suffit de demander. Croyez-moi; cela fonctionnera à court terme et à long terme.

CAVEAT

A l'étape 6, si mysql ne peut pas redémarrer en raison de la suppression du schéma mysql, commencez par revenir à l'étape 2. Vous avez créé la copie physique du schéma mysql. Vous pouvez le restaurer comme suit:

_mkdir /var/lib/mysql/mysql
cp /var/lib/mysql_grants/* /var/lib/mysql/mysql
chown -R mysql:mysql /var/lib/mysql/mysql
_

Retournez à l'étape 6 et continuez

MISE À JOUR 2013-06-04 11:13 EDT

En ce qui concerne la définition de innodb_log_file_size à 25% de innodb_buffer_pool_size à l'étape 5, cette règle générale est plutôt ancienne.

De retour sur _July 03, 2006_, Percona avait publié un bel article pourquoi choisir innodb_log_file_size approprié . Plus tard, le _Nov 21, 2008_, Percona a publié un autre article sur comment calculer la taille appropriée en fonction de la charge de travail maximale en conservant une heure de modifications .

Depuis, j'ai écrit des articles dans DBA StackExchange sur le calcul de la taille du journal et la référence de ces deux articles Percona.

Personnellement, je voudrais toujours aller avec la règle des 25% pour une configuration initiale. Ensuite, comme la charge de travail peut être déterminée avec plus de précision dans le temps en production, vous pouvez redimensionner les journaux pendant un cycle de maintenance en juste quelques minutes.

341
RolandoMySQLDBA

Le moteur InnoDB ne stocke pas les données supprimées. Lorsque vous insérez et supprimez des lignes, l'espace non utilisé est laissé dans les fichiers de stockage InnoDB. Au fil du temps, l'espace total ne diminuera pas, mais au fil du temps, l'espace "supprimé et libéré" sera automatiquement réutilisé par le serveur de base de données.

Vous pouvez affiner et gérer davantage l'espace utilisé par le moteur via une réorganisation manuelle des tables. Pour ce faire, exportez les données dans les tables affectées à l'aide de mysqldump, supprimez les tables, redémarrez le service mysql, puis recréez les tables à partir des fichiers de vidage.

4
bigjeff