J'ai une grande base de données MySql (150 Go) et seulement maintenant, j'ai remarqué que le innodb_file_per_table
est défini sur off
, ce qui fait que la base de données entière est hébergée sur un seul fichier (ibdata1
). Je veux activer innodb_file_per_table
et la diviser rétroactivement en plusieurs fichiers, quelle est la meilleure façon de procéder?
Il n'y a vraiment qu'une seule façon d'y parvenir. Vous devrez exporter les données à l'aide de mysqldumps, supprimer toutes les bases de données, arrêter mysqld, supprimer ib_logfile0, supprimer ib_logfile1, supprimer ibdata1, ajouter innodb_file_per_table
sous le [mysqld]
titre, démarrez mysql.
J'ai posté cette réponse dans StackOverflow en octobre 2010
Voici les étapes répertoriées verticalement:
Étape 01) MySQLDump toutes les bases de données dans un fichier texte SQL (appelez-le SQLData.sql)
Étape 02) Supprimez toutes les bases de données (sauf le schéma mysql)
Étape 03) Arrêtez mysql
[~ # ~] mise en garde [~ # ~] : pour supprimer totalement les transactions non validées des fichiers InnoDB, exécutez cette
mysql -uroot -p... -Ae"SET GLOBAL innodb_fast_shutdown = 0;"
service mysql stop
É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
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 se réduira réellement.
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. !!!
Il existe une alternative qui extraira la table InnoDB sans rétrécir ibdata1.
Étape 01) 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
Étape 02) service mysql restart
Étape 03) Pour extraire une seule table InnoDB appelée mydb.mytable, procédez comme suit:
ALTER TABLE mydb.mytable ENGINE=InnoDB;
Cela va créer un fichier pleus garder le fichier de structure d'origine
Vous pouvez le faire pour chaque table InnoDB. Malheureusement, ibdata1 restera 150 Go.
Si vous voulez récupérer l'espace d'ibdata, un vidage/restauration est votre seul choix, comme le souligne Rolando . Il est également préférable que les performances le fassent.
Cependant, si vous voulez simplement réduire vos pertes et "perdre" ces 150 Go sur le disque dur, vous pouvez simplement activer innodb_file_per_table
dans my.cnf et redémarrez votre serveur.
Ensuite, pour chaque table, lancez:
ALTER TABLE x DISABLE KEYS;
ALTER TABLE x ENGINE=InnoDB;
ALTER TABLE x ENABLE KEYS;
Le problème ici est que les grands espaces de table prendront un certain temps.
Ce que je suggérerais, c'est de configurer un esclave de votre base de données en direct, d'exécuter la conversion sur l'esclave, puis d'éteindre le maître/esclave et de copier le nouvel espace de données sur le maître, ou de promouvoir l'esclave pour qu'il soit maître une fois qu'il a rattrapé le retard. .
Vous allez avoir du mal à effectuer ce changement sans aucun temps d'arrêt.