2013-06-10 8 views
0

Nous avons un système écrit en PHP qui s'est développé au fil des années. La base de données est MySQL (tables InnoDB) avec actuellement plus de 12 Go de données, il y a des centaines de tables, dont beaucoup ont plus de 12 millions d'enregistrements! Le problème est que beaucoup de tables/colonnes (mais pas toutes) sont en latin1, et nous avons (évidemment) des problèmes pour stocker des caractères étrangers. Quelle est la meilleure façon pour nous de convertir toutes les tables/colonnes de texte en UTF8, avec le temps d'arrêt le plus court possible?Convertir énorme base de données de Latin1 à UTF8?

Le système est utilisé par des centaines de personnes 24 heures sur 24, 7 jours sur 7, ce qui fait qu'il n'est vraiment pas possible d'avoir de longs temps d'arrêt.

Existe-t-il de manière réussie sans beaucoup de temps d'arrêt, et y at-il des choses évidentes dont nous devons faire attention?

Je sais que nous aurons besoin de mettre les choses suivantes pour notre utilisation de l'application utf-8:

  • <meta http-equiv="content-type" content="text/html; charset=utf-8" />
  • ini_set('default_charset', 'utf-8');
  • SET NAMES utf8
  • fichiers codés en UTF8 dans notre IDE avant charger le fichier

J'ai lu divers autres messages, mais tout le monde semble suggérer des méthodes différentes, certains disent qu'il a besoin d'un vidage/restauration complet de la base de données ... ce qui signifie des heures et des heures d'arrêt.

Alors, quelle est la meilleure façon de le faire?

+0

Avez-vous essayé de lire cette question: http://stackoverflow.com/questions/2543993/convert-a-mysql-database-from-latin-to-utf-8 –

+0

Je demandais s'il y avait une méthode de faire ceci sans dumping et réimportant toute la base de données, cependant. Une restauration complète va probablement signifier environ 15+ heures de temps d'arrêt que je devine. Nous avons un serveur de base de données de sauvegarde sur lequel nous répliquons tout. Je recherche une meilleure solution que 15+ heures de temps d'arrêt, peut-être quelques idées de réplication intelligentes qui font de notre copie de sauvegarde UTF8 donc nous pouvons simplement commuter – BT643

+0

Vous pouvez convertir des tables individuelles une à la fois avec 'alter table jeu de caractères utf8'. Cela devrait être raisonnablement rapide pour les petites tables, donc vous pouvez le faire avec la base de données en cours d'exécution, donc seules les grandes tables avec des millions d'enregistrements sont un problème. – Joni

Répondre

0

Vous espérez faire quelque chose qui est possible, mais très dur, et risqué aussi bien. Abandonner intelligent: il n'y a rien de magique qui rend cela facile. Vous échangez contre les temps d'arrêt d'une part contre votre coût de main-d'œuvre et le risque de perte de données d'autre part. Votre coût de main-d'œuvre sera probablement dix fois plus élevé que si vous preniez les 15 heures d'arrêt.

Est-il possible d'écrire une requête SELECT pour chaque table qui garantit l'extraction de chaque ligne ajoutée ou modifiée depuis une date donnée, et ce rapidement? Si c'est le cas, écrivez cette requête pour chaque table et gardez-la à portée de main. Sinon, vous ne pouvez pas utiliser cette méthode.

Vous pouvez le faire table par table.

Les petites tables ne prendront pas beaucoup à faire; vous pouvez probablement les faire pendant que votre application est en direct aux heures creuses. Convertissez simplement les colonnes.

Si vous n'avez jamais mis à jour de plus grandes tables, vous pouvez créer des copies de ces tables avec le jeu de caractères et le classement par défaut souhaités pour les colonnes en question. Vous pouvez ensuite copier les données avec INSERT ... SELECT. (http://dev.mysql.com/doc/refman/5.1/en/insert-select.html) Enfin, avec quelques instants de temps d'arrêt, vous pouvez renommer la table de production, puis donner à la nouvelle table le nom de la table de production. Vous devrez peut-être le faire en morceaux de quelques milliers de lignes pour empêcher le système d'intégrité des transactions d'InnoDB de dégrader la RAM de votre serveur.

Enfin, vous devez gérer vos grandes tables et vos tables à langer.Encore une fois, copiez les tables avec INSERT ... SELECT, de manière à ce que les transactions InnoDB ne suspendent pas le fonctionnement de votre application et ne libèrent pas votre RAM. L'intention ici est d'avoir un instantané de votre table à une certaine date/heure.

Ensuite, arrêtez la production. Utilisez votre requête handy-dandy pour sélectionner toutes les lignes insérées et modifiées depuis votre heure de début, et insérez/mettez-les à jour dans votre table cible. Renommez ensuite votre table de production et attribuez le nom de la table de production à votre table cible, puis redémarrez la production. Vous devriez être capable de le faire assez rapidement.

Si j'étais vous, je ferais une copie de mise en scène de votre base de données de production en direct et répétez chaque étape de cette procédure avant de le faire en direct. Vous allez rencontrer des problèmes avec les contraintes de clé étrangère dans InnoDB par exemple; vous devez être capable de travailler à travers ceux-ci avec soin.

En fait, si j'étais vous, je ne voudrais pas essayer de le faire. C'est comme remplacer le moteur d'un avion pendant que l'avion vole. Qu'est-ce qui pourrait mal se passer? :-) Au lieu de cela, j'encouragerais l'interruption programmée de l'application web pour que cette conversion soit faite. Même dans ce cas, vous devriez essayer le tout sur un serveur de mise en scène avant d'aller vivre.

+0

Ok, cela a du sens, donc si je vais pour l'option la plus sûre et que je prends juste le temps d'arrêt. Quelle est la méthode * correcte * pour le faire? J'essaie juste maintenant sur notre serveur de test de voir approximativement combien de temps le temps d'arrêt sera, en utilisant la méthode dans cette question: http://stackoverflow.com/questions/2543993/convert-a-mysql-database-from-latin -to-utf-8 Mais je reçois des problèmes étranges, ça prend * ages * (plus de 10 minutes à ce jour) pour supprimer une seule table afin qu'elle puisse ré-importer les données ... avec MySQL 5.5.29 sur Ubuntu Server 12.04. – BT643

+0

Semble à moi comme vous devriez désactiver les contraintes (sur votre serveur de transfert). Essayez 'SET FOREIGN_KEY_CHECKS = 0;' –

Questions connexes