Lors de migration de bases, ou tout simplement restauration de dump, un des problèmes les plus courants est d'avoir des problèmes d'encodage de caractères.
L'encodage de caractères est complexe sous MySQL car il peut être géré à plusieurs niveaux (serveur, base, table, etc.).
Voici donc quelques astuces qui peuvent servir (ou pas) :
Il faut préciser `CHARACTER SET latin1` ou `CHARACTER SET utf8` notamment si des tables ont des encodages différents !
Par exemple, si l'on a des dumps .txt de tables au format latin1 et utf8, on fera ainsi :
~~~
$ grep CHARSET=latin1 *.sql
$ grep CHARSET=utf8 *.sql
~~~
En fonction des résultats, on réinjectera les données .txt ainsi :
~~~
$ echo "LOAD DATA INFILE '$PWD/<table>.txt' INTO TABLE <table>" CHARACTER SET utf8 | mysql <db>; done
$ echo "LOAD DATA INFILE '$PWD/<table>.txt' INTO TABLE <table>" CHARACTER SET latin1 | mysql <db>; done
~~~
## Purger une table InnoDB (fichier .ibd)
En utilisant l'option `innodb_file_per_table` cela crée des fichiers .ibd par table. Lors d'une suppression de lignes, l'espace
n'est pas libéré immédiatement, il faut ensuite faire un OPTIMIZE TABLE pour "purger" les fichiers .ibd
## Reset mot de passe MySQL
Si vous avez oublié le mot de passe MySQL admin, vous pouvez relancer le démon MySQL ainsi :
~~~
$ /usr/bin/mysqld_safe --skip-grant-tables
130314 16:47:10 mysqld_safe Logging to syslog.
130314 16:47:10 mysqld_safe Starting mysqld daemon with databases from /var/lib/mysql
~~~
Vous pourrez ainsi accéder à MySQL sans mot de passe, et aller changer le mot de passe admin dans la table `mysql.user`.
## Indexes désactivés
Si des requêtes "normales" semblent très lentes, vérifier que les indexes ne sont pas désactivés !
En effet, on peut désactiver les indexes avec un requête : `ALTER TABLE ... DISABLE KEYS`
Pour le vérifier, on vérifiera via un `SHOW INDEXES FROM <table>`
Pour le réactiver (cela peut être long) : `ALTER TABLE ... ENABLE KEYS`
## Cache désactivé
MySQL dispose d'un cache, par exemple si vous faites deux fois un SELECT identique (et simple) sur une table qui n'a pas été modifiée, le 2ème SELECT devrait être renvoyé par le CACHE.
Pour vérifier que cela fonctionne, vous pouvez observer le compteur de cache hits :
~~~
mysql> show status like 'Qcache_hits';
+---------------+--------+
| Variable_name | Value |
+---------------+--------+
| Qcache_hits | 544667 |
+---------------+--------+
1 row in set (0.00 sec)
~~~
Un bug vicieux impacte MySQL 5.1 et 5.5 (corrigé à partir de 5.6.9) : si le nom de la base comporte des caractères spéciaux (le `-` par exemple) et que les tables sont en InnoDB… **le cache ne marche pas !!!!**
Voir http://bugs.mysql.com/bug.php?id=64821 et http://dev.mysql.com/doc/relnotes/mysql/5.6/en/news-5-6-9.html
## Erreur avec base InnoDB
~~~
InnoDB: A new raw disk partition was initialized or
InnoDB: innodb_force_recovery is on: we do not allow
InnoDB: database modifications by the user. Shut down
InnoDB: mysqld and edit my.cnf so that newraw is replaced
InnoDB: with raw, and innodb_force_... is removed.
~~~
The total number of locks exceeds the lock table size
## Erreur 'The total number of locks exceeds the lock table size' on query.
Il faut augmenter la valeur de `innodb_buffer_pool_size`.
## Error 24
Si vous obtenez des erreurs de ce type, lors d'un mysqldump par exemple :
~~~
mysqldump: Got error: 1016: Can't open file: './db/table.frm' (errno: 24) when using LOCK TABLES
mysqldump: Got error: 23: Out of resources when opening file '.\db\table.MYD' (Errcode: 24) when using LOCK TABLES
~~~
C'est que votre serveur MySQL tente d'ouvrir trop de fichiers simultanément.
Pour augmenter le nombre maximal de fichiers pouvant être ouverts, vous pouvez ajuster le paramètre suivant dans la section `[mysqld]` du fichier `my.cnf`, dans la limite permise par votre système d'exploitation :
~~~
open_files_limit = 2048
~~~
La valeur par défaut étant de 1024.
Note : inutile de positionner une valeur pour `ulimit -n` dans les scripts de démarrage, mysqld_safe s'en charge tout seul.
## Problème de _definer_ avec les vues
Un problème classique qui peut arriver suite à une migration d'une base de données contenant des vues. Si l'utilisateur qui a créé la vue (le _definer_) n'existe pas sur le nouveau serveur, la vue sera inutilisable:
~~~
mysql> SELECT * FROM myview;
MySQL ERROR 1449 (HY000) : The user specified as a definer ('root'@'localhost') does not exist
~~~
Il faut donc soit faire un sed dans le dump MySQL pour remplacer le definer si on est à l'étape de préparation de la migration.
Si la migration a déjà été faite et qu'il n'est plus possible de réinjecter un dump, il faut modifier la vue via `ALTER VIEW`, mais il est nécessaire d'indiquer la définition complète de la vue. Pour la connaitre:
~~~
mysql> SHOW CREATE VIEW myview;
~~~
Copier ensuite la définition complète, en remplaçant `CREATE` par `ALTER`, et bien sûr le definer de la vue par un utilisateur existant qui aura les droits sur la vue.
Pour lister les vues dans une base:
~~~
mysql> SHOW FULL TABLES IN mydb WHERE TABLE_TYPE LIKE 'VIEW';
~~~
## Error 2020
Si vous obtenez l'erreur suivante lors d'un mysqldump :
~~~
mysqldump: Error 2020: Got packet bigger than 'max_allowed_packet' bytes when dumping table `mytable` at row: 6542
~~~
Augmentez la valeur de `max_allowed_packet` dans la section `[mysqldump]` du fichier `my.cnf` :
~~~{.ini}
[mysqldump]
max_allowed_packet = 64M
~~~
## Error 1267
Si vous obtenez une erreur du type :
~~~
ERROR 1267 (HY000): Illegal mix of collations (binary,IMPLICIT) and (utf8_bin,NONE) for operation 'like'
~~~
C'est qu'il y a souci entre votre charset client (`character_set_client`, `collation_connection`) et votre requête.
Vous pouvez les ajuster avec des commandes du type :
~~~
mysql> set character_set_client=utf8;
Query OK, 0 rows affected (0.00 sec)
mysql> set collation_connection=utf8_unicode_ci;
Query OK, 0 rows affected (0.00 sec)
~~~
Dans certain cas (création d'une vue par exemple), cela peut venir d'une version de MySQL trop ancienne
(on a constaté des requêtes qui passaient en 5.1 mais pas en 5.0).
## Column count of mysql.proc is wrong
Si vous avez des erreurs de ce type :
~~~
[ERROR] Column count of mysql.db is wrong. Expected 22, found 20. The table is probably corrupted
[ERROR] mysql.user has no `Event_priv` column at position 29
[ERROR] Event Scheduler: An error occurred when initializing system tables. Disabling the Event Scheduler.
[ERROR] Column count of mysql.proc is wrong. Expected 20, found 16. The table is probably corrupted
~~~
Cela signifie que les tables de la base `mysql` ne correspondent pas à la version de MySQL en cours.
Vous avez sûrement mis à jour MySQL ou réinjecter des données d'une autre base.
Plusieurs solutions, réinjecter les tables incorrectes ou utilisez `mysql_upgrade` qui est sensé adapter les tables.
Si vous obtenez l'erreur ci-dessus, lors d'un mysqldump par exemple, et que les fichier `${mysql_datadir}/base/table.{MYD,MYI}` sont vides mais pas le `.frm`, il faut réparer la table comme ceci: