**Astuce très utile** : pour effectuer des requêtes non prises en compte par la réplication, une astuce est d'utiliser interactivement `SET sql_log_bin` ce qui n'écrira pas les requêtes SQL suivantes dans le binlog du serveur (et elles ne seront donc pas répliquées au serveur SLAVE) :
### Configuration de la réplication via fichier de configuration
La configuration d'une réplication via la commande `CHANGE MASTER TO […]` est persistente, elle est notamment conservée en cas de redémarrage de MySQL car conservée dans le fichier `master.info` situé par défaut dans le datadir (**y compris le mot de passe en clair!**). Nous conseillons cette méthode, mais on peut également configurer via la configuration de MySQL ainsi :
> *Note* : En cas d'une bande passante réduite, l'option *slave_compressed_protocol* permet une compression des données côté MASTER et décompression des données côté SLAVE (cela consomme évidemment davantage de ressources CPU).
Une manière d'avoir une réplication peut être de ne pas écrire toutes les requêtes dans les [binlogs](/HowtoMySQL#binlogs) sur le serveur MASTER via les options *binlog_do_db*/*binlog_ignore_db* mais ce n'est pas conseillé car les binlogs ont souvent d'autres utilités (vérifier les requêtes, ou servir pour d'autres serveurs SLAVE).
Une manière différente (ou complémentaire) est d'utiliser les directives *replicate-do-db*/*replicate-ignore-db*/*replicate-do-table*/*replicate-ignore-table*/*replicate-wild-do-table*/*replicate-wild-ignore-table* sur le serveur SLAVE.
/!\\ Ces directives ne sont pas parfaites, notamment les requêtes « croisées » du type `USE foo; UPDATE bar.baz SET […]` ne seront pas comprises, ce qui peut poser des problèmes !
Pour ignorer les requêtes concernant la base _mysql_ :
~~~{.ini}
[mysqld]
replicate-ignore-db = mysql
~~~
Pour n'inclure que les requêtes concernant les bases _foo_ et _bar_ :
~~~{.ini}
[mysqld]
replicate-do-db = foo
replicate-do-db = bar
~~~
Pour n'inclure que les requêtes concernant les tables _foo.baz_ et _foo.qux_ :
~~~{.ini}
[mysqld]
replicate-do-db = foo
replicate-do-table = foo.baz
replicate-do-table = foo.qux
~~~
/!\\ **On conseille de toujours utiliser *replicate-do-db* en complément de *replicate-do-table*/*replicate-wild-do-table* sinon les requêtes non spécifiques aux tables ne sont pas filtrées (…par exemple les DROP DATABASE venant du serveur MASTER !!)**
Les directives *replicate-wild-do-table*/*replicate-wild-ignore-table* permettent d'utiliser des expressions régulières avec `%` et `_` (comme pour l'opérateur SQL _LIKE_), exemple :
Il est important de savoir qu'utiliser une réplication MySQL MASTER/MASTERimplique :
- de ne pas considérer un INSERT comme immédiatement écrit, il pourrait y avoir un délai de quelques secondes (il faut donc bannir un code qui ferait un INSERT puis un SELECT immédiat de la ligne insérée)
- d'éviter la directive `NOW()` dans ses requêtes SQL (valable aussi dans le cas MASTER/SLAVE)
La règle de base de la réplication MySQLest : **un serveur SLAVE ne peut avoir qu'un seul MASTER**.
Cela n'empêche pas d'avoir plusieurs serveurs SLAVE pour un serveur MASTER. Et les serveurs SLAVEpeuvent également être MASTER de plusieurs serveurs SLAVES... ce qui permet de faire des chaînes complexes de réplications.
Exemple avec 3 serveurs MASTER/MASTER/MASTER :
~~~
Serveur A -> Serveur B -> Serveur C [-> Serveur A]
Dans ces cas, il est important d'activer l'option *log-slave-updates* permettant de générer des binlogs à partir des données reçues via la réplication et permettre ainsi d'être MASTER et transmettre ces données à un autre serveur SLAVE :
> **Note** : On pourrait penser que `log-slave-updates` provoque une boucle dans une situation master-master. Mais MySQL est « intelligent », il va ignorer les requêtes de réplications qui contiennent son server-id. A → B (avec server-id de A) → A (ignoré).
En cas d'erreur, il faut «simplement» résoudre l'erreur, puis relancer la réplication avec la commande `START SLAVE`. Voici quelques erreurs possibles :
Si pour une raison ou un autre, on a plein de **DUPLICATE ENTRY** mais que l'est *sûr* de vouloir les ignorer, on peut faire cela en redémarrant MySQL avec le paramètre : `slave-skip-errors = 1062` ; on peut faire également cela avec d'autres types d'erreurs. Malheureusement, il faut forcément redémarrer MySQL car cette commande ne se fait pas à chaud : <http://bugs.mysql.com/bug.php?id=35611>
On peut également avoir d'autres erreurs, par exemple _Could not execute Delete_rows event on table foo.bar; Can't find record in 'bar', Error_code: 1032; handler error HA_ERR_KEY_NOT_FOUND; the event's master log [...]_ et on mettre cette fois `slave-skip-errors = 1032`
On peut également utilisé un script Shell plus évolué qui prendre les motifs à ignorer dans un fichier *error.txt* (expressions rationnelles étendues, compatibles _grep -E_) et qui proposera de zapper manuellement (ou pas) si l'erreur ne correspondant aux motifs :
[ERROR] Error reading packet from server: Client requested master to start replication from impossible position (server_errno=1236)
~~~
Cela signifie que la position indiquée sur le binlog du master est impossible à récupérer. On peut le vérifier avec une commande du type `mysqlbinlog mysqld-bin.00123 --start-position=251` sur le master.
Si l'on constate que le binlog est corrompu avec des erreurs du type _ERROR: Error in Log_event::read_log_event(): 'read error' # Warning: this binlog is either in use or was not closed properly._ ou _ERROR: Error in Log_event::read_log_event(): 'Event too small', data_len: 0, event_type: 0_ l'idée est d'identifier les requêtes non jouées sur le slave dans le binlog corrompu (voir le *Relay_Master_Log_File* via `SHOW SLAVE STATUS`) et de les rejouer (cf [HowtoMySQL#Replay]()) puis de passer au binlog suivant via une commande du type `CHANGE MASTER TO MASTER_LOG_FILE='mysql-bin.000124' , MASTER_LOG_POS=106; START SLAVE;` (la position à indiquer est souvent `106`, cf `mysqlbinlog mysql-bin.000124`).
Si l'on juge cela non nécessaire (données non critiques), on pourra bien sûr passer directement au binlog suivant en ignorant les requêtes du binlog corrompu. Bien sûr, suite à ces manipulations risquées, on vérifiera ensuite la cohérence de la base de données répliquée (`COUNT(*)` ou outils plus avancés).
Could not parse relay log event entry. The possible reasons are: the master's binary log is corrupted (you can check this by running 'mysqlbinlog' on the binary log),
the slave's relay log is corrupted (you can check this by running 'mysqlbinlog' on the relay log), a network problem, or a bug in the master's or slave's MySQL code.
If you want to check the master's binary log or slave's relay log, you will be able to know their names by issuing 'SHOW SLAVE STATUS' on this slave.
**Note**: Jusqu'à MySQL <= 5.1 au moins, changer la position dans un `Relay_log` avec un `CHANGE MASTER TO` ne marche pas. Voir [Changement de la position dans un Relay_log](#ChangementdelapositiondansunRelay_log).
Erreur : `Got fatal error 1236 from master when reading data from binary log: 'log event entry exceeded max_allowed_packet; Increase max_allowed_packet on master'`
* L'un d'eux serait si max_allowed_packet est inférieur à read_buffer_size ; voir <http://www.mysqlperformanceblog.com/2012/06/06/read_buffer_size-can-break-your-replication/> ;
* dans d'autre cas, il faudra forcer la réplication à se poursuivre via `STOP SLAVE; CHANGE MASTER TO MASTER_LOG_FILE='mysql-bin.00XXXX' , MASTER_LOG_POS=XXXX; START SLAVE;`
* dans un autre cas, la position indiquée n'existe pas dans le binlog
Dans certains cas **exceptionnels**, une solution radicale est de réinitialiser la réplication avec un `STOP SLAVE; RESET SLAVE; START SLAVE;` Attention, cela doit être fait dans de très rares cas maîtrisés (attention notamment aux conflits _DUPLICATE ENTRY_ que cela risque de provoquer).
Error initializing relay log position: Could not find target log during
relay log initialization
~~~
Il faut alors stopper le processus slave de réplication:
~~~
mysql> STOP SLAVE;
~~~
Puis éditer (en gardant une sauvegarde) le fichier `${datadir}/relay-log.info`. La première ligne correspond au `Relay_Log_File`, la seconde au `Relay_Log_Pos`.
### Ré-intégré dans la réplication une base qui aurait été exclu.
Dans cet exemple, la base avait été exclu de la réplication, avec `replicate-ignore-db`, les lectures des requêtes de la base est ignoré sur le slave, mais le master continue d'écrire les requêtes de la base dans les binlogs.
1 - On enlève l'exclusion de la base dans le fichier de configuration :
~~~
#replicate-ignore-db = foo
~~~
2 - On fait un dump de cette base sur le *master* :
~~~
# mysqldump foo > foo.sql
~~~
3- On ré-injecte ce dump sur le *slave* :
~~~
# mysql -o foo < foo.sql
~~~
4- On redémarre MySQL (ou l'instance) sur le *slave*, pour qu'il relise le fichier de configuration et ignore l'exclusion de la base sur le slave :
~~~
# systemctl restart mysql.service
~~~
S'il s'agit d'une instance, exemple si l'instance se trouve sur le port 3307 :
~~~
# mysqladmin -P 3307 shutdown
# mysqld_multi start 1
~~~
En cas de réplication master - master, avec un slave de chaque côté, il faut le faire des deux côtés.
Il existe d'autres méthodes, pour faire cela, celle-ci est la plus simple et elle a l'avantage de gérés les locks des tables, on ne doit pas le faire à la main.
C'est un outil de [Percona](https://www.percona.com/downloads/percona-toolkit/) intégré dans son toolkit. (Package Debian [percona-toolkit](https://packages.debian.org/search?keywords=percona-toolkit) disponible à partir de Wheezy).
L'outil vérifie l'intégrité de la réplication en effectuant des requêtes de checksum (crc32 par défaut) sur le master, puis les requêtes sont joués sur les slaves permettant de trouver des différences.
La méthode la plus simple pour l'utiliser est d'autoriser le master à se connecter au slave (authentification MySQL). Ainsi, il s'occupe lui-même de faire le nécessaire pour identifier les erreurs. Il suffira donc de lancer la commande sans argument pour qu'il identifie les incohérences. On pourra réaliser un cron avec l'argument `-q` qui ne fait remonter que les erreurs.
Si on veut afficher seulement les différences on peut utiliser l'option `--replicate-check-only` exemple avec un pt-table-checksum sur une base en particulier:
Si *pt-table-checksum* vous a remonté des incohérences, vous pouvez avec cet outil les corriger. Cela va identifier les différences et les corriger avec un `REPLACE` sur le master (qui sera donc répliqué sur le slave), garantissant la cohérence des données.
En cas de `Can't make changes on the master because no unique index exists`. On peut synchroniser directement les différences sur le slave depuis le master.