Comment resynchroniser la base de données Mysql si le maître et l'esclave ont une base de données différente en cas de réplication Mysql?


139

Mysql Server1fonctionne en tant que MASTER .
Mysql Server2fonctionne en tant que SLAVE .

Désormais, la réplication de la base de données s'effectue du MASTER vers SLAVE .

Server2est supprimé du réseau et reconnectez-le après 1 jour. Après cela, il y a une discordance dans la base de données du maître et de l'esclave.

Comment resynchroniser à nouveau la base de données comme après la restauration de la base de données prise du maître vers l'esclave ne résout pas non plus le problème?

Réponses:


287

Voici la procédure étape par étape complète pour resynchroniser une réplication maître-esclave à partir de zéro:

Chez le maître:

RESET MASTER;
FLUSH TABLES WITH READ LOCK;
SHOW MASTER STATUS;

Et copiez les valeurs du résultat de la dernière commande quelque part.

Sans fermer la connexion au client (car cela libérerait le verrou de lecture), émettez la commande pour obtenir un vidage du maître:

mysqldump -u root -p --all-databases > /a/path/mysqldump.sql

Vous pouvez maintenant libérer le verrou, même si le vidage n'est pas encore terminé. Pour ce faire, exécutez la commande suivante dans le client MySQL:

UNLOCK TABLES;

Copiez maintenant le fichier de vidage sur l'esclave en utilisant scp ou votre outil préféré.

À l'esclave:

Ouvrez une connexion à mysql et tapez:

STOP SLAVE;

Chargez le vidage des données du maître avec cette commande de console:

mysql -uroot -p < mysqldump.sql

Synchroniser les journaux esclaves et maîtres:

RESET SLAVE;
CHANGE MASTER TO MASTER_LOG_FILE='mysql-bin.000001', MASTER_LOG_POS=98;

Où les valeurs des champs ci-dessus sont celles que vous avez copiées auparavant.

Enfin, tapez:

START SLAVE;

Pour vérifier que tout fonctionne à nouveau, après avoir tapé:

SHOW SLAVE STATUS;

tu devrais voir:

Slave_IO_Running: Yes
Slave_SQL_Running: Yes

C'est tout!


8
Avec la dabatase typée INNODB et d'autres types de colonnes complexes comme BLOB et DATE définis, je recommande d'utiliser les commutateurs suivants:--opt --single-transaction --comments --hex-blob --dump-date --no-autocommit --all-databases
Ken Pega

4
Est RESET_SLAVEnécessaire? Notez que ces instructions réinitialisent l'utilisateur et le mot de passe de réplication, vous devrez donc les saisir à nouveau avecCHANGE MASTER TO...
Mike S.

25
Si vous utilisez l'indicateur --master-data lors de l'appel de mysqldump sur le maître, la commande CHANGE MASTER TO est écrite dans le fichier de vidage et enregistre ainsi l'étape de son exécution après l'importation du fichier de vidage dans l'esclave.
udog

3
Ne pas verrouiller le maître (ne nécessite pas Percona) plusbryan.com/mysql-replication-without-downtime Un autre avantage de ceci est que le vidage SQL est également livré avec la ligne "CHANGE MASTER" nécessaire (commentée)
mahemoff

2
Existe-t-il un moyen d'automatiser cela?
Metafaniel

26

La documentation pour cela sur le site MySQL est terriblement obsolète et criblée de pistolets à pied (tels que interactive_timeout). L'émission de FLUSH TABLES WITH READ LOCK dans le cadre de votre exportation du maître n'a généralement de sens que lorsqu'elle est coordonnée avec un instantané de stockage / système de fichiers tel que LVM ou zfs.

Si vous envisagez d'utiliser mysqldump, vous devriez plutôt vous fier à l'option --master-data pour vous protéger contre les erreurs humaines et libérer les verrous sur le maître le plus rapidement possible.

Supposons que le maître est 192.168.100.50 et que l'esclave est 192.168.100.51, chaque serveur a un identifiant de serveur distinct configuré, le maître a une connexion binaire et l'esclave a en lecture seule = 1 dans my.cnf

Pour préparer l'esclave afin de pouvoir démarrer la réplication juste après l'importation du vidage, exécutez une commande CHANGE MASTER mais omettez le nom et la position du fichier journal:

slaveserver> CHANGE MASTER TO MASTER_HOST='192.168.100.50', MASTER_USER='replica', MASTER_PASSWORD='asdmk3qwdq1';

Émettez le GRANT sur le maître pour que l'esclave utilise:

masterserver> GRANT REPLICATION SLAVE ON *.* TO 'replica'@'192.168.100.51' IDENTIFIED BY 'asdmk3qwdq1';

Exportez le maître (à l'écran) en utilisant la compression et en capturant automatiquement les coordonnées correctes du journal binaire:

mysqldump --master-data --all-databases --flush-privileges | gzip -1 > replication.sql.gz

Copiez le fichier replication.sql.gz sur l'esclave, puis importez-le avec zcat dans l'instance de MySQL exécutée sur l'esclave:

zcat replication.sql.gz | mysql

Démarrez la réplication en envoyant la commande à l'esclave:

slaveserver> START SLAVE;

Mettez éventuellement à jour /root/.my.cnf sur l'esclave pour stocker le même mot de passe root que le maître.

Si vous êtes sur 5.1+, il est préférable de régler d'abord le binlog_format du maître sur MIXED ou ROW. Attention, les événements enregistrés par ligne sont lents pour les tables dépourvues de clé primaire. C'est généralement mieux que la configuration alternative (et par défaut) de l'instruction binlog_format = (sur le maître), car il est moins susceptible de produire des données erronées sur l'esclave.

Si vous devez (mais probablement pas) filtrer la réplication, faites-le avec les options esclaves replicate-wild-do-table = dbname.% Ou replicate-wild-ignore-table = badDB.% Et utilisez uniquement binlog_format = row

Ce processus maintiendra un verrou global sur le maître pendant toute la durée de la commande mysqldump mais n'aura aucun impact sur le maître.

Si vous êtes tenté d'utiliser mysqldump --master-data --all-databases --single-transaction (car vous n'utilisez que des tables InnoDB), vous êtes peut-être mieux servi en utilisant MySQL Enterprise Backup ou l'implémentation open source appelée xtrabackup (avec la permission de Percona)


3
Si vous souhaitez simplement reconstruire un esclave existant, vous pouvez suivre le processus ci-dessus, en sautant quelques étapes: La commande GRANT et la commande manuelle CHANGE MASTER
Obsolète

Question 1: Sur Windows, quel serait l'équivalent de zcat . Question 2: Comment cela se passe-t-il mysqldumpavec de grandes bases de données en termes de performances? Une façon d'utiliser SELECT INTO OUTFILEet en LOAD DATAdouceur dans votre processus suggéré? (Comme ils sont généralement plus rapides)
Ifedi Okonkwo

Pas besoin de STOP SLAVEquelque part dans le processus?
David V. le

16

À moins que vous n'écriviez directement sur l'esclave (Serveur2), le seul problème devrait être que le Serveur2 manque toutes les mises à jour qui se sont produites depuis sa déconnexion. Redémarrer simplement l'esclave avec "START SLAVE;" devrait tout remettre en marche.


2
Vous pouvez vérifier les journaux de bac et voir s'ils couvrent la période pendant laquelle votre système n'était pas synchronisé. Si vous manquez des jours, cela peut être un problème plus important et vous obliger à effectuer un vidage complet pour restaurer les données manquantes.
nelaaro

7

Je pense que les utilitaires Maatkit vous aident! Vous pouvez utiliser mk-table-sync. Veuillez consulter ce lien: http://www.maatkit.org/doc/mk-table-sync.html


Je pense qu'il devra temporairement arrêter les écritures lors de l'exécution du script.
Ztyx

Cela fonctionne toujours très bien. Les outils ont cependant été renommés et s'appellent désormais pt-table-sync. En fait, cependant, j'ai trouvé que leur outil pt-slave-restart fonctionne comme par magie.
mlerley

7

Je suis très en retard pour cette question, mais j'ai rencontré ce problème et, après de nombreuses recherches, j'ai trouvé ces informations de Bryan Kennedy: http://plusbryan.com/mysql-replication-without-downtime

Sur Master, faites une sauvegarde comme ceci:
mysqldump --skip-lock-tables --single-transaction --flush-logs --hex-blob --master-data = 2 -A> ~ / dump.sql

Maintenant, examinez la tête du fichier et notez les valeurs de MASTER_LOG_FILE et MASTER_LOG_POS. Vous en aurez besoin plus tard: head dump.sql -n80 | grep "MASTER_LOG"

Copiez le fichier "dump.sql" sur Slave et restaurez-le: mysql -u mysql-user -p <~ / dump.sql

Connectez-vous à Slave mysql et exécutez une commande comme celle-ci: CHANGE MASTER TO MASTER_HOST = 'master-server-ip', MASTER_USER = 'replication-user', MASTER_PASSWORD = 'slave-server-password', MASTER_LOG_FILE = 'value from above', MASTER_LOG_POS = valeur d'en haut; START SLAVE;

Pour vérifier la progression de l'esclave: SHOW SLAVE STATUS;

Si tout va bien, Last_Error sera vide et Slave_IO_State signalera «En attente de l'envoi d'événement par le maître». Recherchez Seconds_Behind_Master qui indique à quelle distance il se trouve. YMMV. :)


3
Cela fonctionne, et si l'esclave est déjà configuré et n'est plus synchronisé, vous n'avez pas besoin d'exécuter CHANGE MASTER; spécifiez simplement --master-data=1(ou juste --master-data).
LSerni

5

Voici ce que je fais généralement lorsqu'un esclave mysql se désynchronise. J'ai regardé mk-table-sync mais j'ai trouvé que la section Risques était effrayante.

Sur Master:

SHOW MASTER STATUS

Les colonnes produites (Fichier, Position) nous seront utiles dans un instant.

Sur esclave:

STOP SLAVE

Puis videz la base de données maître et importez-la dans la base de données esclave.

Ensuite, exécutez ce qui suit:

CHANGE MASTER TO
  MASTER_LOG_FILE='[File]',
  MASTER_LOG_POS=[Position];
START SLAVE;

Où [File] et [Position] sont les valeurs sorties de "SHOW MASTER STATUS" exécuté ci-dessus.

J'espère que cela t'aides!


5
Cela semble cassé, car apparemment, vous n'avez pas FLUSH TABLES WITH READ LOCK;avant vous SHOW MASTER STATUSet vider la base de données principale. Je pense que cela pourrait entraîner par exemple des erreurs de clé en double sur l'esclave puisque vous définissez effectivement le statut du maître à un moment précis avant que le vidage ne soit effectué, vous allez donc rejouer l'historique qui est déjà inclus dans le vidage. (Si vous faites les choses dans l'ordre que vous avez décrit.)
KajMagnus

5

Suite à la réponse de David ...

L'utilisation SHOW SLAVE STATUS\Gdonnera une sortie lisible par l'homme.


Un moyen de paginer la sortie?
Josiah

Je pense que je vais le faire
Ian

3

parfois tu as juste besoin de donner un coup de pied à l'esclave aussi

essayer

stop slave;    
reset slave;    
start slave;    
show slave status;

assez souvent, les esclaves, ils sont juste coincés les gars :)


... et surveiller Positionsur le maître en utilisant show master status;contre Exec_Master_Log_Pos:sur l'esclave en utilisant show slave status \G. L'esclave doit rattraper le maître. J'ai travaillé pour moi en utilisant mysql 5.6 tout à l'heure après une courte panne de réseau.
Mike S

10
Ceci est trompeur, une fois que vous avez réinitialisé l'esclave, le baume a totalement perdu la connaissance de l'endroit où se trouve le maître.
Qian Chen

2

Voici une réponse complète qui, espérons-le, aidera les autres ...


Je veux configurer la réplication mysql en utilisant le maître et l'esclave, et comme la seule chose que je savais était qu'il utilise des fichiers journaux pour se synchroniser, si l'esclave se déconnecte et se désynchronise, en théorie, il ne devrait avoir qu'à se reconnecter à son maître et continuez à lire le fichier journal là où il s'est arrêté, comme l'a mentionné l'utilisateur malonso.

Voici donc le résultat du test après la configuration du maître et de l'esclave comme mentionné par: http://dev.mysql.com/doc/refman/5.0/en/replication-howto.html ...

Pourvu que vous utilisiez la configuration maître / esclave recommandée et que vous n'écriviez pas sur l'esclave, lui et moi étaient corrects (en ce qui concerne mysql-server 5.x). Je n'ai même pas eu besoin d'utiliser "START SLAVE;", il a juste rattrapé son maître. Mais il y a un 88000 par défaut, quelque chose réessaye toutes les 60 secondes, donc je suppose que si vous épuisez, vous devrez peut-être démarrer ou redémarrer l'esclave. Quoi qu'il en soit, pour ceux comme moi qui voulaient savoir si la mise hors ligne et la sauvegarde d'un esclave nécessite une intervention manuelle ... non, ce n'est pas le cas.

Peut-être que l'affiche originale avait une corruption dans le (s) fichier (s) journal? Mais très probablement pas seulement un serveur hors ligne pendant une journée.


extrait de /usr/share/doc/mysql-server-5.1/README.Debian.gz, ce qui a probablement du sens pour les serveurs non Debian également:

* AUTRES REMARQUES SUR LA RÉPLICATION
================================
Si le serveur MySQL agit comme un esclave de réplication, vous ne devez pas
set --tmpdir pour pointer vers un répertoire sur un système de fichiers basé sur la mémoire ou vers
un répertoire qui est effacé lorsque l'hôte du serveur redémarre. Une réplication
l'esclave a besoin de certains de ses fichiers temporaires pour survivre à un redémarrage de la machine.
qu'il peut répliquer des tables temporaires ou des opérations LOAD DATA INFILE. Si
les fichiers du répertoire de fichiers temporaires sont perdus lors du redémarrage du serveur,
la réplication échoue.

vous pouvez utiliser quelque chose de sql comme: show variables comme 'tmpdir'; découvrir.


Les deux bases de données se synchroniseront-elles automatiquement entre elles? Par exemple, j'écris au maître, l'esclave sera-t-il mis à jour automatiquement?
TransformBinary

2

Ajout à la réponse populaire pour inclure cette erreur:

"ERROR 1200 (HY000): The server is not configured as slave; fix in config file or with CHANGE MASTER TO",

Réplication depuis l'esclave en un seul coup:

Dans une fenêtre de terminal:

mysql -h <Master_IP_Address> -uroot -p

Après la connexion,

RESET MASTER;
FLUSH TABLES WITH READ LOCK;
SHOW MASTER STATUS;

L'état apparaît comme ci-dessous: Notez que le numéro de position varie!

+------------------+----------+--------------+------------------+
| File             | Position | Binlog_Do_DB | Binlog_Ignore_DB |
+------------------+----------+--------------+------------------+
| mysql-bin.000001 |      98  | your_DB      |                  |
+------------------+----------+--------------+------------------+

Exportez le dump comme il l'a décrit "en utilisant un autre terminal "!

Quittez et connectez-vous à votre propre DB (qui est l'esclave):

mysql -u root -p

Tapez les commandes ci-dessous:

STOP SLAVE;

Importez le Dump comme mentionné (dans un autre terminal, bien sûr!) Et tapez les commandes ci-dessous:

RESET SLAVE;
CHANGE MASTER TO 
  MASTER_HOST = 'Master_IP_Address', 
  MASTER_USER = 'your_Master_user', // usually the "root" user
  MASTER_PASSWORD = 'Your_MasterDB_Password', 
  MASTER_PORT = 3306, 
  MASTER_LOG_FILE = 'mysql-bin.000001', 
  MASTER_LOG_POS = 98; // In this case

Une fois connecté, définissez le paramètre server_id (généralement, pour les DB nouveaux / non répliqués, il n'est pas défini par défaut),

set global server_id=4000;

Maintenant, démarrez l'esclave.

START SLAVE;
SHOW SLAVE STATUS\G;

La sortie doit être la même que celle décrite.

  Slave_IO_Running: Yes
  Slave_SQL_Running: Yes

Remarque: une fois répliqués, le maître et l'esclave partagent le même mot de passe!


Les deux bases de données se synchroniseront-elles automatiquement entre elles? Par exemple, j'écris au maître, l'esclave sera-t-il mis à jour automatiquement?
TransformBinary

1

Reconstruire l'esclave avec LVM

Voici la méthode que nous utilisons pour reconstruire les esclaves MySQL à l'aide de Linux LVM. Cela garantit un instantané cohérent tout en nécessitant un temps d'arrêt très minimal sur votre maître.

Définissez le pourcentage de pages sales innodb max sur zéro sur le serveur MySQL maître. Cela forcera MySQL à écrire toutes les pages sur le disque, ce qui accélérera considérablement le redémarrage.

set global innodb_max_dirty_pages_pct = 0;

Pour surveiller le nombre de pages modifiées, exécutez la commande

mysqladmin ext -i10 | grep dirty

Une fois que le nombre cesse de diminuer, vous avez atteint le point de continuer. Ensuite, réinitialisez le maître pour effacer les anciens journaux de bac / journaux de relais:

RESET MASTER;

Exécutez lvdisplay pour obtenir le chemin LV

lvdisplay

La sortie ressemblera à ceci

--- Logical volume ---
LV Path                /dev/vg_mysql/lv_data
LV Name                lv_data
VG Name                vg_mysql

Arrêtez la base de données master avec la commande

service mysql stop

Ensuite, prenez un instantané, mysql_snapshot sera le nouveau nom de volume logique. Si des binlogs sont placés sur le lecteur du système d'exploitation, ils doivent également être instantanés.

lvcreate --size 10G --snapshot --name mysql_snapshot /dev/vg_mysql/lv_data

Redémarrez le maître avec la commande

service mysql start

Restaurer le paramètre de pages sales à la valeur par défaut

set global innodb_max_dirty_pages_pct = 75;

Exécutez à nouveau lvdisplay pour vous assurer que l'instantané est présent et visible

lvdisplay

Production:

--- Logical volume ---
LV Path                /dev/vg_mysql/mysql_snapshot
LV Name                mysql_snapshot
VG Name                vg_mysql

Monter l'instantané

mkdir /mnt/mysql_snapshot
mount /dev/vg_mysql/mysql_snapshot /mnt/mysql_snapshot

Si vous avez un esclave MySQL existant en cours d'exécution, vous devez l'arrêter

service mysql stop

Ensuite, vous devez effacer le dossier de données MySQL

cd /var/lib/mysql
rm -fr *

De retour au maître. Maintenant, resynchronisez l'instantané sur l'esclave MySQL

rsync --progress -harz /mnt/mysql_snapshot/ targethostname:/var/lib/mysql/

Une fois rsync terminé, vous pouvez démonter et supprimer l'instantané

umount /mnt/mysql_snapshot
lvremove -f /dev/vg_mysql/mysql_snapshot

Créer un utilisateur de réplication sur le maître si l'ancien utilisateur de réplication n'existe pas ou si le mot de passe est inconnu

GRANT REPLICATION SLAVE on *.* to 'replication'@'[SLAVE IP]' identified by 'YourPass';

Vérifiez que les fichiers de données / var / lib / mysql appartiennent à l'utilisateur mysql, si c'est le cas, vous pouvez omettre la commande suivante:

chown -R mysql:mysql /var/lib/mysql

Enregistrez ensuite la position du binlog

ls -laF | grep mysql-bin

Vous verrez quelque chose comme

..
-rw-rw----     1 mysql mysql  1073750329 Aug 28 03:33 mysql-bin.000017
-rw-rw----     1 mysql mysql  1073741932 Aug 28 08:32 mysql-bin.000018
-rw-rw----     1 mysql mysql   963333441 Aug 28 15:37 mysql-bin.000019
-rw-rw----     1 mysql mysql    65657162 Aug 28 16:44 mysql-bin.000020

Ici, le fichier journal principal est le numéro de fichier le plus élevé dans la séquence et la position du journal du bac est la taille du fichier. Enregistrez ces valeurs:

master_log_file=mysql-bin.000020
master_log_post=65657162

Ensuite, démarrez l'esclave MySQL

service mysql start

Exécutez la commande change master sur l'esclave en exécutant ce qui suit:

CHANGE MASTER TO 
master_host="10.0.0.12", 
master_user="replication", 
master_password="YourPass", 
master_log_file="mysql-bin.000020", 
master_log_pos=65657162; 

Enfin démarrer l'esclave

SLAVE START;

Vérifier l'état de l'esclave:

SHOW SLAVE STATUS;

Assurez-vous que Slave IO est en cours d'exécution et qu'il n'y a pas d'erreurs de connexion. Bonne chance!

BR, Juha Vehnia

J'ai récemment écrit ceci sur mon blog qui se trouve ici ... Il y a quelques détails supplémentaires mais l'histoire est la même.

http://www.juhavehnia.com/2015/05/rebuilding-mysql-slave-using-linux-lvm.html


0

J'ai créé un dépôt GitHub avec un script pour résoudre ce problème rapidement. Changez simplement quelques variables et exécutez-le (d'abord, le script crée une sauvegarde de votre base de données).

J'espère que cela vous aidera (et d'autres personnes aussi).

Comment réinitialiser (resynchroniser) la réplication maître-esclave MySQL


Je vois que le script définit toujours la position du journal principal sur 1 et le nom du fichier journal principal. Je n'en sais pas assez pour être sûr que cela m'inquiète ou non. Pourriez-vous expliquer? J'ai un poste de plus de 1 000 000 actuellement. Cela signifie-t-il qu'il essaiera de rejouer des requêtes de 1 mil avant de se mettre à niveau? N'y a-t-il pas des risques de corruption en jouant ces requêtes contre les données existantes? Je me demande pourquoi pas dans le script lorsque vous effectuez un vidage mysql, utilisez l'option --master-data = 2, puis tirez le fichier et la position hors du vidage pour les définir?
Josiah

0

Nous utilisons la technique de réplication maître-maître de MySQL et si un serveur MySQL dit que 1 est supprimé du réseau, il se reconnecte après la restauration de la connexion et tous les enregistrements qui ont été validés dans le serveur 2 qui était dans le réseau sont transférés au serveur 1 qui a perdu la connexion après la restauration. Le thread esclave dans MySQL essaie de se connecter à son maître toutes les 60 secondes par défaut. Cette propriété peut être modifiée car MySQL a un indicateur "master_connect_retry = 5" où 5 est en sec. Cela signifie que nous voulons une nouvelle tentative toutes les 5 secondes.

Mais vous devez vous assurer que le serveur qui a perdu la connexion ne fait aucun commit dans la base de données lorsque vous obtenez une erreur de clé en double Code d'erreur: 1062


0

Maître :

mysqldump -u root -p --all-databases --master-data | gzip > /tmp/dump.sql.gz  

scp master:/tmp/dump.sql.gz slave:/tmp/ Déplacer le fichier de vidage vers le serveur esclave

Esclave:

STOP SLAVE;

zcat /tmp/dump.sql.gz | mysql -u root -p

START SLAVE;
SHOW SLAVE STATUS;  

REMARQUE :
sur le maître, vous pouvez exécuter SET GLOBAL expire_logs_days = 3pour conserver les binlogs pendant 3 jours en cas de problèmes d'esclave.

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.