MySql - changer innodb_file_per_table pour une base de données live

18

J'ai une grande base de données MySql (150 Go) et seulement maintenant, j'ai remarqué que la valeur innodb_file_per_tableest définie sur offce qui provoque l' hébergement de la totalité de la base de données sur un seul fichier ( ibdata1). Je veux l'activer innodb_file_per_tableet le diviser rétroactivement en plusieurs fichiers, quelle est la meilleure façon de le faire?

Ran
la source

Réponses:

32

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_tablesous l'en- [mysqld]tête, démarrer 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

CAVEAT : pour nettoyer totalement les transactions non validées des fichiers InnoDB, exécutez ce

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

  • 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 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 extrait 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

  • /var/lib/mysql/mydb/mytable.frm
  • /var/lib/mysql/mydb/mytable.ibd

Vous pouvez le faire pour chaque table InnoDB. Malheureusement, ibdata1 restera 150 Go.

RolandoMySQLDBA
la source
lors de l'exécution du rechargement à partir des fichiers .sql, j'ai eu l'erreur suivante ERROR 1071 (42000) at line 25: Specified key was too long; max key length is 1000 bytesdes idées?
Ran
@Ran veuillez poster cela comme une question distincte.
RolandoMySQLDBA
Si vous définissez innodb_file_per_tablepuis effectuez la ALTER TABLEsur chaque table, pouvez-vous supprimer le fichier ibdata1 pour récupérer l'espace sans avoir à restaurer?
SystemParadox
1
@SystemParadox ABSOLUMENT PAS !!!!!!!! Vous perdrez le dictionnaire de données.
RolandoMySQLDBA
5

Si vous souhaitez 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 souhaitez simplement réduire vos pertes et «perdre» ces 150 Go sur le disque dur, vous pouvez simplement activer innodb_file_per_tablele fichier my.cnf et redémarrer 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.

Derek Downey
la source
+1 pour avoir été brutalement honnête et avoir dit "réduisez vos pertes". Vous auriez pu aussi dire «mordez la balle».
RolandoMySQLDBA
Vous pouvez utiliser pt-online-schema-change pour éviter les temps d'arrêt lors de l'exécution de la table alter.
cornernote