La réplication avec GTID (Global Transaction Identifiers) simplifie grandement la gestion de la synchronisation des données entre un serveur MySQL maître et ses répliques. Chaque transaction exécutée sur le maître reçoit un identifiant unique et global qui est consigné dans le journal binaire (binlog). Les répliques utilisent ces GTID pour s'assurer qu'elles appliquent chaque transaction une seule fois, garantissant ainsi la cohérence des données et évitant les doublons ou les pertes.
Comprendre les GTID
Un GTID est composé de deux parties : l'UUID du serveur qui a exécuté la transaction et un numéro de séquence transactionnel. Sa structure est UUID:numéro_transaction. Par exemple, c9fba9e2-db3b-11eb-81d4-000c298d8da1:1-5.
Les avantages des GTID incluent :
- Configuration et gestion simplifiées de la réplication.
- Fiabilité accrue grâce à l'unicité et la séquence des transactions.
- Absence de trous dans la séquence des transactions, garantissant une récupération de données sans perte.
Principe de fonctionnement des GTID
- Le maître enregistre un GTID unique avant chaque transaction dans le binlog.
- Le thread d'E/S de la réplique lit le binlog du maître et le copie dans son propre journal relais (relay log).
- Le thread SQL de la réplique lit les GTID du relay log. Il vérifie ensuite si ces GTID ont déjà été exécutés en consultant son propre binlog (le binlog doit être activé sur la réplique pour cette vérification).
- Si le GTID a déjà été exécuté, la transaction est ignorée.
- Sinon, la transaction correspondante est exécutée à partir du relay log et enregistrée dans le binlog de la réplique.
Mise en place de la réplication GTID
Ce guide utilise deux serveurs : un maître (192.168.152.253, CentOS 7) et une réplique (192.168.152.252, CentOS 8). Une base de données de test nommée vfan avec une table student est utilisée.
1. Configuraton des serveurs MySQL
Modifiez le fichier de configuration de MySQL (my.cnf ou équivalent) sur les deux serveurs et redémarrez le service. Les configurations doivent être similaires, sauf pour le server-id.
server-id=100 # Identifiant unique du serveur
log-bin=/var/lib/mysql/mysql-bin # Activation et emplacement du journal binaire
expire_logs_days=10 # Durée de conservation des journaux binaires
gtid_mode=on # Activation du mode GTID
enforce_gtid_consistency=on # Application stricte de la cohérence GTID (obligatoire avec gtid_mode=on)
binlog_format=row # Format des journaux binaires (ROW est recommandé pour GTID)
skip_slave_start=1 # Empêche le démarrage automatique de la réplication au lancement de MySQL
2. Création de l'utilisateur de réplication sur le maître
Créez un utilisateur sur le serveur maître que la réplique utilisera pour se connecter.
CREATE USER 'copy'@'192.168.152.252' IDENTIFIED BY 'copy';
GRANT REPLICATION SLAVE ON *.* TO 'copy'@'192.168.152.252';
FLUSH PRIVILEGES;
Vérifiez que cet utilisateur peut se connecter depuis la réplique.
3. Synchronisation initiale des données
Utilisez mysqldump pour exporter les données du maître, puis importez-les sur la réplique.
-- Sur le serveur maître :
mysqldump -uroot -p[mot_de_passe] vfan > dump2.sql
scp dump2.sql utilisateur@192.168.152.252:/chemin/vers/data/
-- Sur le serveur réplique :
mysql -uroot -p[mot_de_passe] < /chemin/vers/data/dump2.sql
Après cette étape, les données des deux serveurs doivent être identiques.
4. Démarrage de la réplication
Configurez la connexion maître/réplique sur le serveur réplique en utilisant MASTER_AUTO_POSITION=1 pour activer la réplication basée sur GTID.
-- Sur le serveur réplique :
CHANGE MASTER TO MASTER_HOST='192.168.152.253',
MASTER_USER='copy',
MASTER_PASSWORD='copy',
MASTER_PORT=3306,
MASTER_AUTO_POSITION=1;
START SLAVE;
-- Vérifiez le statut de la réplique :
SHOW SLAVE STATUS\G
Les indicateurs Slave_IO_Running et Slave_SQL_Running doivent être Yes.
5. Vérification de la synchronisation
Insérez des données sur le maître et vérifiez qu'elles apparaissent sur la réplique.
-- Sur le maître :
INSERT INTO vfan.student(name,age) VALUES('gogoo',50),('zhazha',25);
-- Sur la réplique :
SELECT * FROM vfan.student;
Si les nouvelles données sont présentes, la réplication GTID de base est correctement configurée.
Récupération après une panne de réplication sans interruption de service
Scénario : La réplique cesse de fonctionner ou le maître tombe en panne. Nous devons restaurer la synchronisation sans interrompre les opérations.
1. Simulation d'insertion de données continue
Exécutez un script sur le maître pour insérer des données aléatoirement afin de simuler une charge continue.
#!/usr/bin/env bash
values=($(find /usr/ -type d | awk -F '/' '{print $NF}' | sort -u))
while true
do
age=$(( $RANDOM%100 ))
name=${values[$(( $RANDOM%6 ))]}
mysql -h127.1 -P3306 -uroot -p[mot_de_passe] -e "INSERT INTO vfan.student(name,age) VALUES('"${name}"',${age});" > /dev/null
sleep $(( $RANDOM%5 ))
done
Laissez ce script s'exécuter.
2. Simulation de l'arrêt de la réplique
Sur la réplique, arrêtez manuellement le processus de réplication.
-- Sur la réplique :
STOP SLAVE;
À ce stade, le maître continue de recevoir des transactions, mais la réplique ne les applique plus.
3. Sauvegarde différentielle avec GTID
Le but est de récupérer la réplique sans perdre les nouvelles transactions appliquées sur le maître depuis l'arrêt de la réplique. Pour cela, nous utilisons mysqldump avec des options spécifiques.
--single-transaction: Permet de réaliser un dump sans verrouiller les tables pendant longtemps, idéal pour les bases de données transactionnelles.--master-data=2: Inclut une directiveCHANGE MASTER TOcommentée dans le dump, ainsi que le GTID actuel du maître.-R: Sauvegarde les procédures stockées et fonctions.
-- Sur le serveur maître :
mysqldump -uroot -p[mot_de_passe] --single-transaction --master-data=2 -R vfan | gzip > dump4.sql.gz
4. Récupération du GTID actuel
Extrayez le GTID du fichier de dump pour connaître les transactions déjà effectuées sur le maître.
zcat dump4.sql.gz | grep "SET @@GLOBAL.GTID_PURGED"
Vous obtiendrez une ligne comme : SET @@GLOBAL.GTID_PURGED=/*!80000 '+'*/ 'c9fba9e2-db3b-11eb-81d4-000c298d8da1:1-228';. Le GTID c9fba9e2-db3b-11eb-81d4-000c298d8da1:1-228 représente toutes les transactions exécutées par le maître jusqu'à la création du dump.
5. Importation des données sur la réplique
Transférez le fichier de dump sur la réplique et importez-le.
-- Sur le serveur réplique :
scp dump4.sql.gz utilisateur@192.168.152.253:/chemin/vers/data/
gunzip /chemin/vers/data/dump4.sql.gz
mysql -uroot -p[mot_de_passe] < /chemin/vers/data/dump4.sql
Après cette étape, la réplique contient les données jusqu'au GTID 1-228.
6. Réinitialisation et configuration de la réplique
Il faut maintenant reconfigurer la réplique pour qu'elle puisse reprendre la synchronisation à partir du bon point, en ignorant les transactions déjà présentes dans la base importée.
- Vérifiez la valeur de
gtid_purgedsur la réplique. Si elle n'est pas vide, réinitialisez-la. - Arrêtez le
SLAVE, réinitialisez-le complètement. - Configurez le
GTID_PURGEDmanuellement pour indiquer les GTID qui ont déjà été appliqués (ceux du dump). - Reconnectez la réplique au maître avec
MASTER_AUTO_POSITION=1.
-- Sur la réplique :
-- Vérifiez et réinitialisez gtid_purged si nécessaire :
SHOW GLOBAL VARIABLES LIKE '%gtid%';
-- Si gtid_purged n'est pas vide, exécutez :
RESET MASTER; -- ATTENTION : Ceci réinitialise le binlog et gtid_purged sur la réplique
-- Arrêter et réinitialiser la réplique :
STOP SLAVE;
RESET SLAVE ALL;
-- Configurer le GTID_PURGED avec la valeur extraite du dump :
SET @@GLOBAL.GTID_PURGED='c9fba9e2-db3b-11eb-81d4-000c298d8da1:1-228';
-- Reconfigurer la connexion maître :
CHANGE MASTER TO MASTER_HOST='192.168.152.253',
MASTER_USER='copy',
MASTER_PASSWORD='copy',
MASTER_PORT=3306,
MASTER_AUTO_POSITION=1;
-- Redémarrer la réplique :
START SLAVE;
7. Vérification de la synchronisation post-récupération
Surveillez le statut de la réplique.
-- Sur la réplique :
SHOW SLAVE STATUS\G
Les indicateurs Slave_IO_Running et Slave_SQL_Running doivent être Yes. L'indicateur Retrieved_Gtid_Set doit montrer les GTID reçus du maître, et Executed_Gtid_Set doit refléter les GTID appliqués. Seconds_Behind_Master doit être 0 ou proche de 0.
8. Validation finale
Comparez le nombre de lignes et le contenu des données entre le maître et la réplique pour confirmer que toutes les transactions ont été synchronisées.
-- Sur le maître :
SELECT COUNT(*) FROM vfan.student;
-- Sur la réplique :
SELECT COUNT(*) FROM vfan.student;
Si les comptes correspondent et que les données sont identiques, la récupération sans interruption de service est réussie.