web-dev-qa-db-fra.com

Quelle est la meilleure façon de réduire la taille d'ibdata dans mysql?

J'ai des serveurs de production dont les fichiers ibdata augmentent de jour en jour.

Il a déjà consommé 290 Go d'espace.

Les tables des serveurs sont principalement InnoDB et les demandes de lecture et d'écriture sont élevées.

La taille du fichier journal augmente également. Il y a une énorme quantité de données dans les tableaux.

Comment puis-je contrôler la taille croissante des deux?

Je n'utilise pas innodb_file_per_table.

66
Abdul Manaf

Gardez à l'esprit que le fichier le plus occupé de l'infrastructure InnoDB est/var/lib/mysql/ibdata1

Ce fichier contient normalement de nombreuses classes d'informations (lorsque innodb_file_per_table est 0)

  • Données de table
  • Index de table
  • Données MVCC (Multiversioning Concurrency Control)
    • Segments de restauration
    • Annuler l'espace disque logique
  • Métadonnées du tableau
  • Voir Représentation picturale

De nombreuses personnes créent plusieurs fichiers ibdata dans l'espoir d'une meilleure gestion de l'espace disque et de meilleures performances. Ça n'aide pas.

Malheureusement, OPTIMIZE TABLE sur une table InnoDB stockée dans ibdata1 fait deux choses:

  • Rend les données et les index de la table contigus dans ibdata1
  • Il fait croître ibdata1 car les données contiguës sont ajoutées à ibdata1

Vous pouvez séparer les données de table et les index de table d'ibdata1 et les gérer indépendamment en utilisant innodb_file_per_table . Pour réduire une fois pour toutes ibdata1, vous devez procéder comme suit

Étape 01) MySQLDump toutes les bases de données dans un fichier texte SQL (appelez-le SQLData.sql) ( Plus de détails ici )

Étape 02) Supprimez toutes les bases de données (sauf mysql, performance_schema, et information_schema)

Étape 03) Arrêtez mysql

Étape 04) Ajoutez les lignes suivantes à /etc/my.cnf

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

Sidenote: Quel que soit votre ensemble pour innodb_buffer_pool_size, assurez-vous que innodb_log_file_size représente 25% de innodb_buffer_pool_size.

Étape 05) Supprimer ibdata1, ib_logfile0 et ib_logfile1

À ce stade, il ne devrait y avoir que le schéma mysql dans/var/lib/mysql

Étape 06) Redémarrez mysql

Cela va recréer ibdata1 à 10 Mo, ib_logfile0 et ib_logfile1 à 1G chacun

Étape 07) Rechargez SQLData.sql dans mysql

ibdata1 augmentera mais ne contiendra que des métadonnées de table

Chaque table InnoDB existera en dehors d'ibdata1

Supposons que vous ayez une table InnoDB nommée mydb.mytable. Si vous allez dans/var/lib/mysql/mydb, vous verrez deux fichiers représentant la table

  • mytable.frm (en-tête du moteur de stockage)
  • mytable.ibd (Accueil des données de table et des index de table pour mydb.mytable)

ibdata1 ne contiendra plus de données et d'index InnoDB.

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 va en fait rétrécir.

Je l'ai fait plusieurs fois dans ma carrière en tant que DBA MySQL

En fait, la première fois que j'ai fait cela, j'ai réduit un fichier ibdata1 de 50 Go en 500 Mo.

Essaie. Si vous avez d'autres questions à ce sujet, écrivez-moi. Croyez-moi. Cela fonctionnera à court terme et à long terme. !!!

Si vous souhaitez voir combien de données réelles sont stockées dans MyISAM et InnoDB, veuillez exécuter cette requête:

SELECT IFNULL(B.engine,'Total') "Storage Engine",
CONCAT(LPAD(REPLACE(FORMAT(B.DSize/POWER(1024,pw),3),',',''),17,' '),' ',
SUBSTR(' KMGTP',pw+1,1),'B') "Data Size", CONCAT(LPAD(REPLACE(
FORMAT(B.ISize/POWER(1024,pw),3),',',''),17,' '),' ',
SUBSTR(' KMGTP',pw+1,1),'B') "Index Size", CONCAT(LPAD(REPLACE(
FORMAT(B.TSize/POWER(1024,pw),3),',',''),17,' '),' ',
SUBSTR(' KMGTP',pw+1,1),'B') "Table Size"
FROM (SELECT engine,SUM(data_length) DSize,SUM(index_length) ISize,
SUM(data_length+index_length) TSize FROM information_schema.tables
WHERE table_schema NOT IN ('mysql','information_schema','performance_schema')
AND engine IS NOT NULL GROUP BY engine WITH ROLLUP) B,
(SELECT 3 pw) A ORDER BY TSize;
110
RolandoMySQLDBA