Une erreur de données de table unique dans le scénario de réplication MySQL maître-esclave entraîne l'arrêt de la réplication Comment réparer rapidement

Description de la scène:

Si les données de la table t de la base de données esclave sont incohérentes avec la base de données maître, ce qui entraîne des erreurs de réplication, la base de données entière contient une grande quantité de données et la restauration de la base de données esclave est lente. Comment récupérer les données de cette seule table?
Il est généralement considéré qu'il est impossible de réparer les données d'une seule table, car l'état de chaque table est incohérent.
La liste suivante répertorie les problèmes et les solutions auxquels la table unique de sauvegarde sera confrontée lors de sa restauration dans la base de données esclave.

1. Description de l'environnement de démonstration:

Serveur physique Dell r620 Les deux
environnements réseau sont
maître intranet : 192.168.1.220
esclave: 192.168.1.217
Environnement système du système d'exploitation: installation minimale de centos7.8 X86_64, ferme iptables, ferme la
version du logiciel de test selinux : paquet binaire mysql5.7.27
à l'avance Configurer la réplication maître-esclave MySQL basée sur Gtid pour
créer des données de test simulées, simuler des scénarios d'échec pour
réparer la réplication maître-esclave MySQL
pt-table-checksum, vérifier si les données de réplication maître-esclave MySQL réparées sont cohérentes

Deux, configurer la réplication maître-esclave

Le processus d'installation de MySQL n'est plus décrit ici, Baidu lui-même

Pour configurer la réplication maître-esclave
afin de configurer un nouvel esclave pour une machine maître, n'oubliez pas d'ajouter le paramètre --set-gtid-purged = ON lorsque mysqldump sauvegarde les données.
Supplément de connaissances:
1. Une sauvegarde régulière consiste à ajouter --set-gtid-purged = OFF résoudre l'avertissement pendant la sauvegarde
[root @ localhost ~] # mysqldump -uroot -p'dXdjVF # (y3lt '--set-gtid-purged = OFF --single-transaction -A -B | gzip> 17/09/2020 .sql.gz
2. Pour la sauvegarde effectuée lors de la construction du maître-esclave, vous n'avez pas besoin d'ajouter le paramètre --set-gtid-purged = OFF, mais vous devez ajouter --set-gtid-purged = ON
[root @ localhost ~] # mysqldump -uroot -p'dXdjVF # (y3lt '--set-gtid-purged = ON --single-transaction -A -B --master-data = 2 | gzip> 2020-09-17.sql.gz
invite:
in Pour créer une réplication maître-esclave, ne la désactivez pas. Pendant la sauvegarde quotidienne, vous pouvez la désactiver.
--Set-gtid-purged = AUTO, ON, OFF
1 .-- set-gtid-purged = OFF peut être utilisé dans les paramètres de sauvegarde quotidiens . 2
.-- = SET-gtid les paramètres oN-Purged requis pour construire la copie principale à partir de la configuration d'environnement

Les étapes spécifiques de configuration de la réplication maître-esclave basée sur Gtid sont les suivantes:

bibliothèque principale:

 grant replication slave on *.* to rep@'192.168.1.217' identified by 'JuwoSdk21TbUser'; flush privileges;
 mysqldump -uroot -p'dXdjVF#(y3lt' --set-gtid-purged=ON --single-transaction -A -B --master-data=2 |gzip > 2020-09-20.sql.gz 

Fonctionnement de la bibliothèque esclave:

 [root@mysql02 ~]# mysql < 2020-09-17.sql 
 mysql>  change master to master_host='192.168.1.220',master_user='rep',master_password='JuwoSdk21TbUser',MASTER_AUTO_POSITION = 1;start slave;show slave status\G
ERROR 29 (HY000): File '/data1/mysql/3306/relaylog/relay-bin.index' not found (Errcode: 2 - No such file or directory)
ERROR 29 (HY000): File '/data1/mysql/3306/relaylog/relay-bin.index' not found (Errcode: 2 - No such file or directory)
Empty set (0.00 sec)

La raison en est que le chemin de stockage du journal de relais est configuré dans la configuration de la machine esclave my.cnf, mais le chemin n'existe pas dans le serveur esclave et une erreur est signalée. Créez le répertoire, autorisez l'autorisation mysql, puis modifiez à nouveau le maître

mkdir -p /data1/mysql/3306/relaylog/
cd /data1/mysql/3306/
chown -R mysql.mysql relaylog
mysql> change master to master_host='192.168.1.220',master_user='rep',master_password='JuwoSdk21TbUser',MASTER_AUTO_POSITION = 1;start slave;show slave status\G

La configuration de la réplication maître-esclave est terminée.

3. Préparez les données de test et simulez l'échec

Créez une table de démonstration de simulation sur la bibliothèque principale, disposez de temporisateurs et de procédures stockées, et écrivez régulièrement des données dans la table de test pour faciliter la création de la table de test pour la démonstration suivante de reprise après échec de réplication maître-esclave
:

 CREATE TABLE `test_event` (
`id` int(8) NOT NULL AUTO_INCREMENT, 
`username` varchar(20) COLLATE utf8_unicode_ci NOT NULL,
`password` varchar(20) COLLATE utf8_unicode_ci NOT NULL, 
`create_time` varchar(20) COLLATE utf8_unicode_ci NOT NULL,
PRIMARY KEY (`id`) #主键ID
) ENGINE=innodb AUTO_INCREMENT=0 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;

Créez une minuterie et écrivez une donnée toutes les secondes après 1 minute à partir de l'heure actuelle:

delimiter $$
create event event_2 
on schedule every 1 second STARTS   CURRENT_TIMESTAMP + INTERVAL 1 MINUTE
COMMENT 'xiaowu create'
do 
    BEGIN
           insert into test_event(username,password,create_time) values("李四","tomcat",now());
    END $$
delimiter ;

Créez une nouvelle table de test txt similaire à la méthode ci-dessus, écrivez des données régulièrement

Échec de la simulation de la bibliothèque esclave:


 insert into test_event(username,password,create_time) values("李四","tomcat",now());
 insert into test_event(username,password,create_time) values("李四","tomcat",now());
 delete from txt where id=200;

Ensuite, supprimez l'enregistrement avec id = 200 sur la bibliothèque
principale Opération principale: supprimer de txt où id = 200;

À ce stade, la bibliothèque esclave vérifie l'état de la réplication et a arrêté la réplication:

[root@mysql02 ~]#  mysql -e "show slave status\G"|grep -A 1 'Last_SQL_Errno'
               Last_SQL_Errno: 1062
               Last_SQL_Error: Coordinator stopped because there were error(s) in the worker(s). The most recent failure being: Worker 1 failed executing transaction '8a9fb9a3-f579-11ea-830d-90b11c12779c:42083' at master log mysql-bin.000001, end_log_pos 18053730. See error log and/or performance_schema.replication_applier_status_by_worker table for more details about this failure or others, if any.

Quatrièmement, reprise après panne

scène 1

Si l'erreur de réplication est signalée, la réplication maître-esclave n'a pas été réparée à l'aide de méthodes telles que le saut d'erreurs et le filtrage de réplication. Les données de la base de données maître ont été mises à jour et les données de la base de données esclave sont bloquées dans un état d'erreur (en supposant que le GTID est 8a9fb9a3-f579-11ea-830d-90b11c12779c: 1-42083).
Étapes de réparation:
table de sauvegarde test_event sur la base de données maître (en supposant que l'instantané de sauvegarde GTID est 8a9fb9a3-f579-11ea-830d-90b11c12779c: 1-42262);
restaurer dans la base de données esclave;
démarrer la réplication.
Le problème ici est que la position de début de réplication est 8a9fb9a3-f579-11ea-830d-90b11c12779c: 42084 et que l'état des données de la table test_event de la bibliothèque est en avance sur les autres tables.
8a9fb9a3-f579-11ea-830d-90b11c12779c: 42084-42262 Dans ces transactions, tant qu'il y a une transaction qui modifie les données de la table test_event, cela provoquera des erreurs de réplication, telles que des conflits de clé primaire et la non-existence d'enregistrement (tandis que 8a9fb9a3-f579-11ea-830d-90b11c: 1-42084, la transaction qui a signalé l'erreur de réplication précédente doit être la transaction qui a modifié la table t)
Solution: ignorez 8a9fb9a3-f579-11ea-830d-90b11c12779c: 42084-42262 dans ces transactions qui modifient la table t lors du démarrage de la réplication.

Les bonnes étapes de réparation:

  1. Sauvegardez la table test_event sur la base de données master (l'instantané de sauvegarde GTID est 8a9fb9a3-f579-11ea-830d-90b11c12779c: 1-42262) et restaurez-le dans la base de données esclave;
  2. Définir le filtre de réplication, filtre de la table t:
    CHANGE REPLICATION FILTER REPLICATE_WILD_IGNORE_TABLE = ('dbtest01.test_event');
  3. Démarrez la copie et arrêtez la copie lorsque la lecture atteint 8a9fb9a3-f579-11ea-830d-90b11c12779c: 1-42262 (les données de toutes les tables de la bibliothèque esclave sont dans le même état à ce moment, ce qui est cohérent);
    START SLAVE JUSQU'À SQL_AFTER_GTIDS = '8a9fb9a3-f579 -11ea-830d-90b11c12779c: 1-42262 ';
  4. Supprimez le filtre de réplication et démarrez la réplication normalement.
    Remarque: utilisez mysqldump --single-transaction --master-data = 2 ici pour enregistrer le GTID correspondant à l'instantané de sauvegarde

Les étapes détaillées sont les suivantes:

A. Pour vider la table test_event qui a provoqué l'arrêt de la réplication sur la bibliothèque maître:

mysqldump -uroot -p'dXdjVF#(y3lt'  --single-transaction dbtest01 test_event --master-data=2 |gzip >$(date +%F).test_event.sql.gz
[root@localhost ~]# mysqldump -uroot -p'dXdjVF#(y3lt'  --single-transaction dbtest01 test_event --master-data=2 |gzip >$(date +%F).test_event.sql.gz
mysqldump: [Warning] Using a password on the command line interface can be insecure.
Warning: A partial dump from a server that has GTIDs will by default include the GTIDs of all transactions, even those that changed suppressed parts of the database. If you don't want to restore GTIDs, pass --set-gtid-purged=OFF. To make a complete dump, pass --all-databases --triggers --routines --events. 

B. Obtenez la valeur gtid de l'instantané d'une table de sauvegarde distincte:

8a9fb9a3-f579-11ea-830d-90b11c12779c: 1-42262

[root@mysql02 ~]# gzip -d 2020-09-17.test_event.sql.gz
[root@mysql02 ~]# grep -A6 'GLOBAL.GTID_PURGED' 2020-09-17.test_event.sql 
SET @@GLOBAL.GTID_PURGED='8a9fb9a3-f579-11ea-830d-90b11c12779c:1-42262';
--
-- Position to start replication or point-in-time recovery from
--
-- CHANGE MASTER TO MASTER_LOG_FILE='mysql-bin.000001', MASTER_LOG_POS=18130552;

C. Restaurez cette table dans la bibliothèque esclave. Étant donné que GTID_EXECUTED n'est pas une valeur nulle, il ne parvient pas à importer la table test_event dans la bibliothèque esclave. L'erreur spécifique est la suivante: Fonctionnement de la bibliothèque esclave
:

[root@mysql02 ~]#  mysql dbtest01 < 2020-09-17.test_event.sql 
ERROR 1840 (HY000) at line 24: @@GLOBAL.GTID_PURGED can only be set when @@GLOBAL.GTID_EXECUTED is empty.

 mysql> select  @@GLOBAL.GTID_EXECUTED;
+----------------------------------------------------------------------------------------+
| @@GLOBAL.GTID_EXECUTED                                                                 |
+----------------------------------------------------------------------------------------+
| 5ec577a4-f401-11ea-bf6d-14187756553d:1-2,
8a9fb9a3-f579-11ea-830d-90b11c12779c:1-42082 |
+----------------------------------------------------------------------------------------+
1 row in set (0.00 sec)

mysql> show master status\G
*************************** 1. row ***************************
             File: mysql-bin.000001
         Position: 368620
     Binlog_Do_DB: 
 Binlog_Ignore_DB: 
Executed_Gtid_Set: 5ec577a4-f401-11ea-bf6d-14187756553d:1-2,
8a9fb9a3-f579-11ea-830d-90b11c12779c:1-42082
1 row in set (0.00 sec)

La solution est de se connecter à la bibliothèque esclave:
mysql> reset master;
cette opération peut vider la valeur GTID_EXECUTED de la bibliothèque courante

[root@mysql02 ~]#  mysql dbtest01 < 2020-09-17.test_event.sql 

mysql> show master status\G
*************************** 1. row ***************************
             File: mysql-bin.000001
         Position: 154
     Binlog_Do_DB: 
 Binlog_Ignore_DB: 
Executed_Gtid_Set: 8a9fb9a3-f579-11ea-830d-90b11c12779c:1-42262
1 row in set (0.00 sec)

D. Ouvrir le filtre de copie en ligne:

mysql> CHANGE REPLICATION FILTER REPLICATE_WILD_IGNORE_TABLE = ('db_name.test_event');
Query OK, 0 rows affected (0.00 sec)

[root@mysql02 ~]# mysql -e "show slave status\G"|egrep 'db_name.test_event'
  Replicate_Wild_Ignore_Table: db_name.test_event

E. Démarrez la copie et arrêtez la copie lors de la lecture vers 8a9fb9a3-f579-11ea-830d-90b11c12779c: 42262 (à ce stade, les données de toutes les tables de la bibliothèque esclave sont dans le même état et cohérentes)

mysql> START SLAVE UNTIL SQL_AFTER_GTIDS ='8a9fb9a3-f579-11ea-830d-90b11c12779c:42262';
Query OK, 0 rows affected, 1 warning (0.03 sec)

mysql> 

Bien que le thread SQL ne soit pas pour le moment, la réplication ne signale plus d'erreur:

[root@mysql02 ~]# mysql -e "show slave status\G"|egrep 'Last_SQL_Error|Slave_IO|Slave_SQL'
               Slave_IO_State: Waiting for master to send event
             Slave_IO_Running: Yes
            Slave_SQL_Running: No
               Last_SQL_Error: 

F. Désactivez le filtrage de réplication en ligne:

mysql> CHANGE REPLICATION FILTER REPLICATE_WILD_IGNORE_TABLE = ();
Query OK, 0 rows affected (0.00 sec)

mysql> 
[root@mysql02 ~]# mysql -e "show slave status\G"|egrep 'db_name.test_event|IO_Running|SQL_Running'
             Slave_IO_Running: Yes
            Slave_SQL_Running: No
      Slave_SQL_Running_State: 

G. Démarrez le thread SQL de réplication esclave:


mysql> start slave sql_thread;
Query OK, 0 rows affected (0.04 sec)

Récupération de réplication maître-esclave:

[root@mysql02 ~]# mysql -e "show slave status\G"|egrep 'IO_Running|SQL_Running'
             Slave_IO_Running: Yes
            Slave_SQL_Running: Yes
      Slave_SQL_Running_State: Slave has read all relay log; waiting for more updates

Remarque: utilisez mysqldump --single-transaction --master-data = 2 ici pour enregistrer le GTID correspondant à l'instantané de sauvegarde

Cinq, vérifiez la cohérence des données maître-esclave

Utilisez l'outil de vérification pt-table-checksum pour vérifier. Pour plus de détails sur l'installation et l'utilisation, veuillez vous référer à l'adresse suivante du blog:
https://blog.51cto.com/wujianwei/2409523


[root@localhost bin]# time /usr/local/percona-toolkit/bin/pt-table-checksum h=192.168.1.220,u=ptsum,p='ptchecksums',P=3306 --ignore-databases sys,mysql  --truncate-replicate-table  --replicate=percona.ptchecksums --no-check-binlog-format --nocheck-replication-filters --recursion-method="processlist"   2>&1 | tee 2020-09-18-pt-checksum.log

Checking if all tables can be checksummed ...
Starting checksum ...
            TS ERRORS  DIFFS     ROWS  DIFF_ROWS  CHUNKS SKIPPED    TIME TABLE
09-18T07:49:09      0      0     9739          0       4       0   0.747 dbtest01.hlz_ad
09-18T07:49:10      0      0    64143          0       4       0   0.968 dbtest01.hlz_ad_step
09-18T07:49:16      0      0   741424          0      10       0   6.014 dbtest01.hlz_bubble
09-18T07:49:18      0      0   499991          0       5       0   1.610 dbtest01.test01
09-18T07:49:25      0      0  3532986          0      13       0   7.802 dbtest01.test02
09-18T07:49:26      0      0   126863          0       1       0   0.976 dbtest01.test_event
09-18T07:49:27      0      1    30294          0       1       0   0.582 test01.txt

real    1m22.725s
user    0m0.387s
sys 0m0.078s

On constate que la table test01.txt de la bibliothèque principale n'est pas cohérente avec la table test01.txt de l'esclave.

La raison est la suivante: à l'instant même dans la démonstration de simulation, l'action de
suppression delete from txt où id = 200 a été exécutée sur la bibliothèque esclave ; résultant en un enregistrement de moins dans la table de bibliothèque esclave txt que dans la table txt de la bibliothèque maître

Données de réparation:

[root@localhost bin]# /usr/local/percona-toolkit/bin/pt-table-sync h=192.168.1.220,u=ptsum,p=ptchecksums,P=3306 --databases=test01 --tables=test01.txt  --replicate=percona.ptchecksums  --charset=utf8  --transaction --execute

Vérifiez à nouveau, les données sont cohérentes


[root@localhost bin]# time /usr/local/percona-toolkit/bin/pt-table-checksum h=192.168.1.220,u=ptsum,p='ptchecksums',P=3306 --ignore-databases sys,mysql  --truncate-replicate-table  --replicate=percona.ptchecksums --no-check-binlog-format --nocheck-replication-filters --recursion-method="processlist"   2>&1 | tee 2020-09-18-pt-checksum.log
Checking if all tables can be checksummed ...
Starting checksum ...
            TS ERRORS  DIFFS     ROWS  DIFF_ROWS  CHUNKS SKIPPED    TIME TABLE
09-18T09:48:10      0      0     9739          0       4       0   0.784 dbtest01.hlz_ad
09-18T09:48:11      0      0    64143          0       4       0   0.995 dbtest01.hlz_ad_step
09-18T09:48:16      0      0   741424          0       9       0   4.224 dbtest01.hlz_bubble
09-18T09:48:17      0      0   499991          0       5       0   1.470 dbtest01.test01
09-18T09:48:24      0      0  3532986          0      13       0   6.403 dbtest01.test02
09-18T09:48:24      0      0   133999          0       1       0   0.894 dbtest01.test_event
09-18T09:48:25      0      0    37431          0       1       0   0.511 test01.txt

real    0m15.676s
user    0m0.359s
sys 0m0.055s

Six, avec un total de cas de test d'internautes

Le cas 2 est joint, ce qui est fondamentalement le même que la scène 1. Je n'entrerai pas dans les détails ici et je laisserai le soin aux internautes intéressés.
Ce qui suit décrit brièvement les scénarios et les méthodes de récupération:

Si l'erreur de réplication est signalée, la réplication maître-esclave peut être réparée à l'aide de méthodes telles que l'ignorance des erreurs et le filtrage de réplication. Les données du maître et de l'esclave sont constamment mises à jour.
Étapes de réparation des erreurs:
table de sauvegarde t sur la base de données principale (en supposant que l'instantané de sauvegarde GTID est aaaa: 1-10000);
arrêtez la copie à partir de la base de données, GTID est aaaa: 1-20000;
restaurez la table t dans la base de données esclave;
démarrez la réplication.

Analyse de la raison:
Le problème ici est que la position de départ de la réplication est aaaa: 20001, aaaa: 10000-20000. Ces transactions ne seront pas lues sur la bibliothèque esclave. S'il y a une transaction qui modifie les données de la table t, la bibliothèque esclave perdra cette transaction. une partie des données

Solution: Du début de la sauvegarde au début de la réplication, verrouillez la table t pour vous assurer qu'aucune transaction ne modifie la table t dans aaaa: 10000-20000.

Corriger les étapes de réparation:

Ajoutez un verrou de lecture à
la table de bibliothèque principale t; table de sauvegarde t sur la bibliothèque principale;
arrêtez la copie à partir de la bibliothèque et restaurez la table t;
commencez la copie;
déverrouillez la table t

Solution suggérée: Si vous ne souhaitez pas verrouiller la table t, vous pouvez suspendre directement la copie de la bibliothèque, puis utiliser le scénario un pour reprendre. Cela évite de verrouiller la table.

Je suppose que tu aimes

Origine blog.51cto.com/wujianwei/2535067
conseillé
Classement